/
greylist.go
64 lines (52 loc) · 1.31 KB
/
greylist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package main
import (
"flag"
"sync"
"time"
)
var minDelay = flag.Duration("delay", 0, "minimum time before a retry is accepted")
// A triplet is a combination of client IP, sender, and recipient.
type triplet struct {
ip string
from string
to string
}
var (
greylist = map[triplet]time.Time{}
ipPassed = map[string]bool{}
// greylistLock protects both of the maps above.
greylistLock sync.RWMutex
)
type greylistAction int
const (
newTriplet greylistAction = iota
tooSoon
passed
)
// CheckGreylist checks and updates the greylist. If the combination of
// ip, from, and to was seen before (and recently enough), it returns true and
// the amount of time the message was delayed. If not, it returns false.
func CheckGreylist(ip, from, to string) (action greylistAction, delay time.Duration) {
greylistLock.Lock()
defer greylistLock.Unlock()
t := triplet{ip, from, to}
now := time.Now()
if oldTime, ok := greylist[t]; ok {
delay = now.Sub(oldTime)
if delay < *minDelay {
return tooSoon, delay
}
if delay < 24*time.Hour {
ipPassed[ip] = true
return passed, delay
}
}
greylist[t] = now
return newTriplet, 0
}
// AlreadyPassed returns whether ip has already passed greylisting.
func AlreadyPassed(ip string) bool {
greylistLock.RLock()
defer greylistLock.RUnlock()
return ipPassed[ip]
}