Selaa lähdekoodia

Initial DLINE changes

tags/v0.5.0
Daniel Oaks 7 vuotta sitten
vanhempi
commit
8c797d0f76
5 muutettua tiedostoa jossa 224 lisäystä ja 10 poistoa
  1. 1
    0
      CHANGELOG.md
  2. 10
    0
      irc/commands.go
  3. 151
    0
      irc/dline.go
  4. 34
    4
      irc/help.go
  5. 28
    6
      irc/server.go

+ 1
- 0
CHANGELOG.md Näytä tiedosto

@@ -10,6 +10,7 @@ New release of Oragono!
10 10
 ### Security
11 11
 
12 12
 ### Added
13
+* Added ability to `DLINE` IP addresses ad networks, to allow for fast blocking.
13 14
 
14 15
 ### Changed
15 16
 

+ 10
- 0
irc/commands.go Näytä tiedosto

@@ -76,6 +76,11 @@ var Commands = map[string]Command{
76 76
 		handler:   debugHandler,
77 77
 		minParams: 1,
78 78
 	},
79
+	"DLINE": {
80
+		handler:   dlineHandler,
81
+		minParams: 1,
82
+		oper:      true,
83
+	},
79 84
 	"HELP": {
80 85
 		handler:   helpHandler,
81 86
 		minParams: 0,
@@ -200,6 +205,11 @@ var Commands = map[string]Command{
200 205
 		handler:   topicHandler,
201 206
 		minParams: 1,
202 207
 	},
208
+	"UNDLINE": {
209
+		handler:   undlineHandler,
210
+		minParams: 1,
211
+		oper:      true,
212
+	},
203 213
 	"USER": {
204 214
 		handler:      userHandler,
205 215
 		usablePreReg: true,

+ 151
- 0
irc/dline.go Näytä tiedosto

@@ -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
+}

+ 34
- 4
irc/help.go Näytä tiedosto

@@ -36,7 +36,8 @@ Oragono supports the following channel modes:
36 36
 
37 37
   +i  |  Invite-only mode, only invited clients can join the channel.
38 38
   +m  |  Moderated mode, only privileged clients can talk on the channel.
39
-  +n  |  No-outside-messages mode, only users that are on the channel can send the channel messages.
39
+  +n  |  No-outside-messages mode, only users that are on the channel can send
40
+      |  messages to it.
40 41
   +t  |  Only channel opers can modify the topic.
41 42
   +s  |  Secret mode, channel won't show up in /LIST or whois replies.
42 43
 
@@ -95,6 +96,26 @@ Prints debug information about the IRCd. <option> can be one of:
95 96
 * STARTCPUPROFILE: Starts the CPU profiler.
96 97
 * STOPCPUPROFILE: Stops the CPU profiler.
97 98
 * PROFILEHEAP: Writes out the CPU profiler info.`,
99
+	},
100
+	"dline": {
101
+		oper: true,
102
+		text: `DLINE [duration] <ip>/<net> [reason [| oper reason]]
103
+
104
+Bans an IP address or network from connecting to the server. If the duration is
105
+given then only for that long. The reason is shown to the user themselves, but
106
+everyone else will see a standard message. The oper reason is shown to
107
+operators getting info about the DLINEs that exist.
108
+
109
+Bans are saved across subsequent launches of the server.
110
+
111
+[duration] can be of the following forms:
112
+	10h 8m 13s
113
+
114
+<net> is specified in typical CIDR notation. For example:
115
+	127.0.0.1/8
116
+	8.8.8.8/24
117
+
118
+[reason] and [oper reason], if they exist, are separated by a vertical bar (|).`,
98 119
 	},
99 120
 	"help": {
100 121
 		text: `HELP <argument>
@@ -250,7 +271,7 @@ Indicates that you're leaving the server, and shows everyone the given reason.`,
250 271
 REG VERIFY <accountname> <auth_code>
251 272
 
252 273
 Used in account registration. See the relevant specs for more info:
253
-https://github.com/DanielOaks/ircv3-specifications/blob/register-and-verify/extensions/reg-core-3.3.md`,
274
+http://oragono.io/specs.html`,
254 275
 	},
255 276
 	"rehash": {
256 277
 		oper: true,
@@ -268,6 +289,16 @@ Shows the time of the current, or the given, server.`,
268 289
 
269 290
 If [topic] is given, sets the topic in the channel to that. If [topic] is not
270 291
 given, views the current topic on the channel.`,
292
+	},
293
+	"undline": {
294
+		oper: true,
295
+		text: `UNDLINE <ip>/<net>
296
+
297
+Removes an existing ban on an IP address or a network.
298
+
299
+<net> is specified in typical CIDR notation. For example:
300
+	127.0.0.1/8
301
+	8.8.8.8/24`,
271 302
 	},
272 303
 	"user": {
273 304
 		text: `USER <username> 0 * <realname>
@@ -316,8 +347,7 @@ Returns historical information on the last user with the given nickname.`,
316 347
 
317 348
 Oragono supports an experimental unicode casemapping designed for extended
318 349
 Unicode support. This casemapping is based off RFC 7700 and the draft rfc7700
319
-casemapping spec here:
320
-https://github.com/DanielOaks/ircv3-specifications/blob/master%2Brfc7700/documentation/rfc7700.md`,
350
+casemapping spec here: http://oragono.io/specs.html`,
321 351
 	},
322 352
 	"prefix": {
323 353
 		text: `RPL_ISUPPORT PREFIX

+ 28
- 6
irc/server.go Näytä tiedosto

@@ -29,6 +29,9 @@ var (
29 29
 	// cached because this may be used lots
30 30
 	tooManyClientsMsg      = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your IP or network")
31 31
 	tooManyClientsBytes, _ = tooManyClientsMsg.Line()
32
+
33
+	bannedFromServerMsg      = ircmsg.MakeMessage(nil, "", "ERROR", "You are banned from this server (%s)")
34
+	bannedFromServerBytes, _ = bannedFromServerMsg.Line()
32 35
 )
33 36
 
34 37
 // Limits holds the maximum limits for various things such as topic lengths
@@ -78,6 +81,7 @@ type Server struct {
78 81
 	connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
79 82
 	ctime                 time.Time
80 83
 	currentOpers          map[*Client]bool
84
+	dlines                *DLineManager
81 85
 	idle                  chan *Client
82 86
 	isupport              *ISupportList
83 87
 	limits                Limits
@@ -190,6 +194,9 @@ func NewServer(configFilename string, config *Config) *Server {
190 194
 	}
191 195
 	server.store = *db
192 196
 
197
+	// load dlines
198
+	server.loadDLines()
199
+
193 200
 	// load password manager
194 201
 	err = server.store.View(func(tx *buntdb.Tx) error {
195 202
 		saltString, err := tx.Get(keySalt)
@@ -342,18 +349,33 @@ func (server *Server) Run() {
342 349
 			// check connection limits
343 350
 			ipaddr := net.ParseIP(IPString(conn.Conn.RemoteAddr()))
344 351
 			if ipaddr != nil {
352
+				// check DLINEs
353
+				isBanned, info := server.dlines.CheckIP(ipaddr)
354
+				if isBanned {
355
+					banMessage := fmt.Sprintf(bannedFromServerBytes, info.Reason)
356
+					if info.Time != nil {
357
+						banMessage += fmt.Sprintf(" [%s]", info.Time.Length.String())
358
+					}
359
+					conn.Conn.Write([]byte(banMessage))
360
+					conn.Conn.Close()
361
+					continue
362
+				}
363
+
364
+				// check connection limits
345 365
 				server.connectionLimitsMutex.Lock()
346 366
 				err := server.connectionLimits.AddClient(ipaddr, false)
347 367
 				server.connectionLimitsMutex.Unlock()
348
-				if err == nil {
349
-					go NewClient(server, conn.Conn, conn.IsTLS)
368
+				if err != nil {
369
+					// too many connections from one client, tell the client and close the connection
370
+					// this might not show up properly on some clients, but our objective here is just to close it out before it has a load impact on us
371
+					conn.Conn.Write([]byte(tooManyClientsBytes))
372
+					conn.Conn.Close()
350 373
 					continue
351 374
 				}
375
+
376
+				go NewClient(server, conn.Conn, conn.IsTLS)
377
+				continue
352 378
 			}
353
-			// too many connections from one client, tell the client and close the connection
354
-			// this might not show up properly on some clients, but our objective here is just to close it out before it has a load impact on us
355
-			conn.Conn.Write([]byte(tooManyClientsBytes))
356
-			conn.Conn.Close()
357 379
 
358 380
 		case client := <-server.idle:
359 381
 			client.Idle()

Loading…
Peruuta
Tallenna