|
@@ -0,0 +1,151 @@
|
|
1
|
+// Copyright (c) 2016- Daniel Oaks <daniel@danieloaks.net>
|
|
2
|
+// released under the MIT license
|
|
3
|
+
|
|
4
|
+package irc
|
|
5
|
+
|
|
6
|
+import "net"
|
|
7
|
+import "time"
|
|
8
|
+
|
|
9
|
+// IPRestrictTime contains the expiration info about the given IP.
|
|
10
|
+type IPRestrictTime struct {
|
|
11
|
+ // Expires is when this block expires.
|
|
12
|
+ Expires time.Time
|
|
13
|
+ // Length is how long this block lasts for.
|
|
14
|
+ Length time.Duration
|
|
15
|
+}
|
|
16
|
+
|
|
17
|
+// IsExpired returns true if the time has expired.
|
|
18
|
+func (iptime *IPRestrictTime) IsExpired() bool {
|
|
19
|
+ return iptime.Expires.Before(time.Now())
|
|
20
|
+}
|
|
21
|
+
|
|
22
|
+// IPBanInfo holds info about an IP/net ban.
|
|
23
|
+type IPBanInfo struct {
|
|
24
|
+ // Reason is the ban reason.
|
|
25
|
+ Reason string
|
|
26
|
+ // OperReason is an oper ban reason.
|
|
27
|
+ OperReason string
|
|
28
|
+ // Time holds details about the duration, if it exists.
|
|
29
|
+ Time *IPRestrictTime
|
|
30
|
+}
|
|
31
|
+
|
|
32
|
+// dLineAddr contains the address itself and expiration time for a given network.
|
|
33
|
+type dLineAddr struct {
|
|
34
|
+ // Address is the address that is blocked.
|
|
35
|
+ Address net.IP
|
|
36
|
+ // Info contains information on the ban.
|
|
37
|
+ Info IPBanInfo
|
|
38
|
+}
|
|
39
|
+
|
|
40
|
+// dLineNet contains the net itself and expiration time for a given network.
|
|
41
|
+type dLineNet struct {
|
|
42
|
+ // Network is the network that is blocked.
|
|
43
|
+ Network net.IPNet
|
|
44
|
+ // Info contains information on the ban.
|
|
45
|
+ Info IPBanInfo
|
|
46
|
+}
|
|
47
|
+
|
|
48
|
+// DLineManager manages and dlines.
|
|
49
|
+type DLineManager struct {
|
|
50
|
+ // addresses that are dlined
|
|
51
|
+ addresses map[string]*dLineAddr
|
|
52
|
+ // networks that are dlined
|
|
53
|
+ networks map[string]*dLineNet
|
|
54
|
+}
|
|
55
|
+
|
|
56
|
+// NewDLineManager returns a new DLineManager.
|
|
57
|
+func NewDLineManager() *DLineManager {
|
|
58
|
+ dm := DLineManager{
|
|
59
|
+ addresses: make(map[string]*dLineAddr),
|
|
60
|
+ networks: make(map[string]*dLineNet),
|
|
61
|
+ }
|
|
62
|
+ return &dm
|
|
63
|
+}
|
|
64
|
+
|
|
65
|
+// AddNetwork adds a network to the blocked list.
|
|
66
|
+func (dm *DLineManager) AddNetwork(network net.IPNet, length *IPRestrictTime) {
|
|
67
|
+ netString := network.String()
|
|
68
|
+ dln := dLineNet{
|
|
69
|
+ Network: network,
|
|
70
|
+ Info: IPBanInfo{
|
|
71
|
+ Time: length,
|
|
72
|
+ Reason: "",
|
|
73
|
+ OperReason: "",
|
|
74
|
+ },
|
|
75
|
+ }
|
|
76
|
+ dm.networks[netString] = &dln
|
|
77
|
+}
|
|
78
|
+
|
|
79
|
+// RemoveNetwork removes a network from the blocked list.
|
|
80
|
+func (dm *DLineManager) RemoveNetwork(network net.IPNet) {
|
|
81
|
+ netString := network.String()
|
|
82
|
+ delete(dm.networks, netString)
|
|
83
|
+}
|
|
84
|
+
|
|
85
|
+// AddIP adds an IP address to the blocked list.
|
|
86
|
+func (dm *DLineManager) AddIP(addr net.IP, length *IPRestrictTime) {
|
|
87
|
+ addrString := addr.String()
|
|
88
|
+ dla := dLineAddr{
|
|
89
|
+ Address: addr,
|
|
90
|
+ Info: IPBanInfo{
|
|
91
|
+ Time: length,
|
|
92
|
+ Reason: "",
|
|
93
|
+ OperReason: "",
|
|
94
|
+ },
|
|
95
|
+ }
|
|
96
|
+ dm.addresses[addrString] = &dla
|
|
97
|
+}
|
|
98
|
+
|
|
99
|
+// RemoveIP removes an IP from the blocked list.
|
|
100
|
+func (dm *DLineManager) RemoveIP(addr net.IP) {
|
|
101
|
+ addrString := addr.String()
|
|
102
|
+ delete(dm.addresses, addrString)
|
|
103
|
+}
|
|
104
|
+
|
|
105
|
+// CheckIP returns whether or not an IP address was banned, and how long it is banned for.
|
|
106
|
+func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
|
|
107
|
+ // check IP addr
|
|
108
|
+ addrString := addr.String()
|
|
109
|
+
|
|
110
|
+ addrInfo := dm.addresses[addrString]
|
|
111
|
+ if addrInfo != nil {
|
|
112
|
+ if addrInfo.Info.Time != nil {
|
|
113
|
+ if addrInfo.Info.Time.IsExpired() {
|
|
114
|
+ // ban on IP has expired, remove it from our blocked list
|
|
115
|
+ dm.RemoveIP(addr)
|
|
116
|
+ } else {
|
|
117
|
+ return true, &addrInfo.Info
|
|
118
|
+ }
|
|
119
|
+ } else {
|
|
120
|
+ return true, nil
|
|
121
|
+ }
|
|
122
|
+ }
|
|
123
|
+
|
|
124
|
+ // check networks
|
|
125
|
+ var netsToRemove []net.IPNet
|
|
126
|
+
|
|
127
|
+ for _, netInfo := range dm.networks {
|
|
128
|
+ if !netInfo.Network.Contains(addr) {
|
|
129
|
+ continue
|
|
130
|
+ }
|
|
131
|
+
|
|
132
|
+ if netInfo.Info.Time != nil {
|
|
133
|
+ if netInfo.Info.Time.IsExpired() {
|
|
134
|
+ // ban on network has expired, remove it from our blocked list
|
|
135
|
+ netsToRemove = append(netsToRemove, netInfo.Network)
|
|
136
|
+ } else {
|
|
137
|
+ return true, &addrInfo.Info
|
|
138
|
+ }
|
|
139
|
+ } else {
|
|
140
|
+ return true, nil
|
|
141
|
+ }
|
|
142
|
+ }
|
|
143
|
+
|
|
144
|
+ // remove expired networks
|
|
145
|
+ for _, expiredNet := range netsToRemove {
|
|
146
|
+ dm.RemoveNetwork(expiredNet)
|
|
147
|
+ }
|
|
148
|
+
|
|
149
|
+ // no matches!
|
|
150
|
+ return false, nil
|
|
151
|
+}
|