mirror of
https://github.com/ergochat/ergo.git
synced 2025-01-13 05:32:36 +01:00
enum types simplifying sort, config fails on wrong action types
This commit is contained in:
parent
5e7aceb75e
commit
6a9fa35d35
@ -101,14 +101,31 @@ type DnsblListEntry struct {
|
|||||||
Types []string
|
Types []string
|
||||||
Reply map[string]DnsblListReply
|
Reply map[string]DnsblListReply
|
||||||
Action string
|
Action string
|
||||||
|
ActionType uint
|
||||||
Reason string
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DnsblListReply struct {
|
type DnsblListReply struct {
|
||||||
Action string
|
Action string
|
||||||
|
ActionType uint
|
||||||
Reason string
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (conf *Config) DnsblTypes(action string) (uint, error) {
|
||||||
|
actions := map[string]uint{
|
||||||
|
"require-sasl": DnsblRequireSaslReply,
|
||||||
|
"allow": DnsblAllowReply,
|
||||||
|
"block": DnsblBlockReply,
|
||||||
|
"notify": DnsblNotifyReply,
|
||||||
|
}
|
||||||
|
|
||||||
|
if value, exists := actions[action]; exists {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return DnsblUnknownReply, errors.New(fmt.Sprintf("Unknown DNSBL action type: %s", action))
|
||||||
|
}
|
||||||
|
|
||||||
type NickReservationMethod int
|
type NickReservationMethod int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -493,12 +510,16 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
config.Server.WebIRC = newWebIRC
|
config.Server.WebIRC = newWebIRC
|
||||||
|
|
||||||
for id, list := range config.Dnsbl.Lists {
|
for id, list := range config.Dnsbl.Lists {
|
||||||
var action, reason = list.Action, list.Reason
|
actionType, err := config.DnsblTypes(list.Action)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reason := list.Reason
|
||||||
|
|
||||||
var newDnsblListReply = make(map[string]DnsblListReply)
|
var newDnsblListReply = make(map[string]DnsblListReply)
|
||||||
for key, reply := range list.Reply {
|
for key, reply := range list.Reply {
|
||||||
if reply.Action == "" {
|
if reply.Action == "" {
|
||||||
reply.Action = action
|
reply.ActionType = actionType
|
||||||
}
|
}
|
||||||
if reply.Reason == "" {
|
if reply.Reason == "" {
|
||||||
reply.Reason = reason
|
reply.Reason = reason
|
||||||
@ -508,6 +529,7 @@ func LoadConfig(filename string) (config *Config, err error) {
|
|||||||
newDnsblListReply[newKey] = reply
|
newDnsblListReply[newKey] = reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
config.Dnsbl.Lists[id].ActionType = actionType
|
||||||
config.Dnsbl.Lists[id].Reply = newDnsblListReply
|
config.Dnsbl.Lists[id].Reply = newDnsblListReply
|
||||||
}
|
}
|
||||||
|
|
||||||
|
93
irc/dnsbl.go
93
irc/dnsbl.go
@ -9,6 +9,16 @@ import (
|
|||||||
"github.com/oragono/oragono/irc/sno"
|
"github.com/oragono/oragono/irc/sno"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const (
|
||||||
|
DnsblRequireSaslReply uint = iota
|
||||||
|
DnsblAllowReply
|
||||||
|
DnsblBlockReply
|
||||||
|
DnsblNotifyReply
|
||||||
|
DnsblUnknownReply
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReverseAddress returns IPv4 addresses reversed
|
||||||
func ReverseAddress(ip net.IP) string {
|
func ReverseAddress(ip net.IP) string {
|
||||||
// This is a IPv4 address
|
// This is a IPv4 address
|
||||||
if ip.To4() != nil {
|
if ip.To4() != nil {
|
||||||
@ -25,12 +35,7 @@ func ReverseAddress(ip net.IP) string {
|
|||||||
return ip.String()
|
return ip.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func LastIpOctet(addr string) string {
|
// LookupBlacklistEntry performs a lookup on the dnsbl on the client IP
|
||||||
address := strings.Split(addr, ".")
|
|
||||||
|
|
||||||
return address[len(address)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) LookupBlacklistEntry(list *DnsblListEntry, client *Client) []string {
|
func (server *Server) LookupBlacklistEntry(list *DnsblListEntry, client *Client) []string {
|
||||||
res, err := net.LookupHost(fmt.Sprintf("%s.%s", ReverseAddress(client.IP()), list.Host))
|
res, err := net.LookupHost(fmt.Sprintf("%s.%s", ReverseAddress(client.IP()), list.Host))
|
||||||
|
|
||||||
@ -42,23 +47,16 @@ func (server *Server) LookupBlacklistEntry(list *DnsblListEntry, client *Client)
|
|||||||
|
|
||||||
if len(res) > 0 {
|
if len(res) > 0 {
|
||||||
for _, addr := range res {
|
for _, addr := range res {
|
||||||
entries = append(entries, LastIpOctet(addr))
|
octet := strings.Split(addr, ".")
|
||||||
|
if len(octet) > 0 {
|
||||||
|
entries = append(entries, octet[len(octet)-1])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendDnsblMessage(client *Client, message string) {
|
|
||||||
/*fmt.Printf(client.server.DnsblConfig().Channel)
|
|
||||||
if channel := client.server.DnsblConfig().Channel; channel != "" {
|
|
||||||
fmt.Printf(channel)
|
|
||||||
client.Send(nil, client.server.name, "PRIVMSG", channel, message)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
client.server.snomasks.Send(sno.Dnsbl, message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessBlacklist does
|
// ProcessBlacklist does
|
||||||
func (server *Server) ProcessBlacklist(client *Client) {
|
func (server *Server) ProcessBlacklist(client *Client) {
|
||||||
|
|
||||||
@ -67,56 +65,51 @@ func (server *Server) ProcessBlacklist(client *Client) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel := server.DnsblConfig().Channel
|
||||||
|
lists := server.DnsblConfig().Lists
|
||||||
|
|
||||||
type DnsblTypeResponse struct {
|
type DnsblTypeResponse struct {
|
||||||
Host string
|
Host string
|
||||||
Action string
|
ActionType uint
|
||||||
Reason string
|
Reason string
|
||||||
}
|
}
|
||||||
var items = []DnsblTypeResponse{}
|
var items = []DnsblTypeResponse{}
|
||||||
for _, list := range server.DnsblConfig().Lists {
|
for _, list := range lists {
|
||||||
response := DnsblTypeResponse{
|
response := DnsblTypeResponse{
|
||||||
Host: list.Host,
|
Host: list.Host,
|
||||||
Action: list.Action,
|
ActionType: list.ActionType,
|
||||||
Reason: list.Reason,
|
Reason: list.Reason,
|
||||||
}
|
}
|
||||||
// update action/reason if matched with new ...
|
// update action/reason if matched with new ...
|
||||||
for _, entry := range server.LookupBlacklistEntry(&list, client) {
|
for _, entry := range server.LookupBlacklistEntry(&list, client) {
|
||||||
if reply, exists := list.Reply[entry]; exists {
|
if reply, exists := list.Reply[entry]; exists {
|
||||||
response.Action, response.Reason = reply.Action, reply.Reason
|
response.ActionType, response.Reason = list.ActionType, reply.Reason
|
||||||
}
|
}
|
||||||
items = append(items, response)
|
items = append(items, response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort responses so that require-sasl blocks come first. Otherwise A>B (allow>block, allow>notify, block>notify)
|
// Sorts in the following order: require-sasl, allow, block, notify
|
||||||
// so that responses come in this order:
|
|
||||||
// - require-sasl
|
|
||||||
// - allow
|
|
||||||
// - block
|
|
||||||
// - notify
|
|
||||||
sort.Slice(items, func(i, j int) bool {
|
sort.Slice(items, func(i, j int) bool {
|
||||||
if items[i].Action == "require-sasl" {
|
return items[i].ActionType > items[j].ActionType
|
||||||
return true
|
|
||||||
}
|
|
||||||
return items[i].Action > items[j].Action
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(items) > 0 {
|
if len(items) > 0 {
|
||||||
item := items[0]
|
item := items[0]
|
||||||
switch item.Action {
|
switch item.ActionType {
|
||||||
case "require-sasl":
|
case DnsblRequireSaslReply:
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s, requiring SASL to proceed", client.IP(), item.Host))
|
client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Connecting client %s matched %s, requiring SASL to proceed", client.IP(), item.Host))
|
||||||
client.SetRequireSasl(true, item.Reason)
|
client.SetRequireSasl(true, item.Reason)
|
||||||
|
|
||||||
case "block":
|
case DnsblBlockReply:
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s - killing", client.IP(), item.Host))
|
client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Connecting client %s matched %s - killing", client.IP(), item.Host))
|
||||||
client.Quit(strings.Replace(item.Reason, "{ip}", client.IPString(), -1))
|
client.Quit(strings.Replace(item.Reason, "{ip}", client.IPString(), -1))
|
||||||
|
|
||||||
case "notify":
|
case DnsblNotifyReply:
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s matched %s", client.IP(), item.Host))
|
client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Connecting client %s matched %s", client.IP(), item.Host))
|
||||||
|
|
||||||
case "allow":
|
case DnsblAllowReply:
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Allowing host %s [%s]", client.IP(), item.Host))
|
client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Allowing host %s [%s]", client.IP(), item.Host))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,13 +123,29 @@ func connectionRequiresSasl(client *Client) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel := client.server.DnsblConfig().Channel
|
||||||
|
|
||||||
if client.Account() == "" {
|
if client.Account() == "" {
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s and did not authenticate through SASL - blocking connection", client.IP()))
|
//client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Connecting client %s and did not authenticate through SASL - blocking connection", client.IP()))
|
||||||
client.Quit(strings.Replace(reason, "{ip}", client.IPString(), -1))
|
client.Quit(strings.Replace(reason, "{ip}", client.IPString(), -1))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
sendDnsblMessage(client, fmt.Sprintf("Connecting client %s authenticated through SASL - allowing", client.IP()))
|
client.sendServerMessage("", channel, sno.Dnsbl, fmt.Sprintf("Connecting client %s authenticated through SASL - allowing", client.IP()))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) sendServerMessage(pseudo string, channel string, mask sno.Mask, message string) {
|
||||||
|
/*
|
||||||
|
This causes an out of bounds error - possibly in client.Send() - investigate further
|
||||||
|
if pseudo == "" {
|
||||||
|
pseudo = client.server.name
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel != "" {
|
||||||
|
client.Send(nil, pseudo, "PRIVMSG", channel, message)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
client.server.snomasks.Send(mask, message)
|
||||||
|
}
|
||||||
|
@ -1784,9 +1784,6 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
|
|
||||||
server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, client.operName))
|
server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, client.operName))
|
||||||
|
|
||||||
// increase oper count
|
|
||||||
//server.stats.ChangeOperators(1)
|
|
||||||
|
|
||||||
// client may now be unthrottled by the fakelag system
|
// client may now be unthrottled by the fakelag system
|
||||||
client.resetFakelag()
|
client.resetFakelag()
|
||||||
|
|
||||||
|
@ -446,11 +446,6 @@ func (server *Server) tryRegister(c *Client) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if connectionRequiresSasl(c) {
|
|
||||||
c.destroy(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// client MUST send PASS (or AUTHENTICATE, if skip-server-password is set)
|
// client MUST send PASS (or AUTHENTICATE, if skip-server-password is set)
|
||||||
// before completing the other registration commands
|
// before completing the other registration commands
|
||||||
if !c.Authorized() {
|
if !c.Authorized() {
|
||||||
@ -467,6 +462,12 @@ func (server *Server) tryRegister(c *Client) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if connection requires SASL
|
||||||
|
if connectionRequiresSasl(c) {
|
||||||
|
c.destroy(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// check KLINEs
|
// check KLINEs
|
||||||
isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...)
|
isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...)
|
||||||
if isBanned {
|
if isBanned {
|
||||||
|
59
oragono.yaml
59
oragono.yaml
@ -407,3 +407,62 @@ fakelag:
|
|||||||
# client status resets to the default state if they go this long without
|
# client status resets to the default state if they go this long without
|
||||||
# sending any commands:
|
# sending any commands:
|
||||||
cooldown: 2s
|
cooldown: 2s
|
||||||
|
# dnsbls are DNS block lists. they're used to automatically deny or restrict clients who
|
||||||
|
# have been deemed bad
|
||||||
|
dnsbl:
|
||||||
|
# whether to check DNS block lists
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# optional channel to send rejections to if the 'notify' action is specified in any lists
|
||||||
|
#channel: "#dnsbl"
|
||||||
|
|
||||||
|
# the specific dnsbls to check for every client entering the network
|
||||||
|
lists:
|
||||||
|
-
|
||||||
|
# host - specific hostname to use
|
||||||
|
host: "dnsbl.dronebl.org"
|
||||||
|
|
||||||
|
# which types of hosts to look up on this dnsbl. we support:
|
||||||
|
# - ipv4: D.C.B.A.hostname
|
||||||
|
# - ipv6: n.i.b.b.l.e.s.hostname (see explanation here: https://www.dan.me.uk/dnsbl )
|
||||||
|
types:
|
||||||
|
- ipv4
|
||||||
|
- ipv6
|
||||||
|
|
||||||
|
# action to take if the client matches this dnsbl:
|
||||||
|
# - allow - let the client access the network
|
||||||
|
# - block - block the client from accessing the network, with the given message
|
||||||
|
# - notify - send a notification to opers in-channel (if configured) and via the 'S' snomask
|
||||||
|
# - require-sasl - require the client to login with SASL, kill them if they don't
|
||||||
|
action: block
|
||||||
|
|
||||||
|
# reason that's shown if they're unable to access the network because of this rbl.
|
||||||
|
# we support the following variables:
|
||||||
|
# - "{ip}" - their IP address
|
||||||
|
reason: "Your IP ({ip}) is listed in DroneBL. For assistance, see http://dronebl.org/lookup?ip={ip}"
|
||||||
|
|
||||||
|
# specific replies to take action on. these are based on the last octet of the return IP.
|
||||||
|
# for example, "24" or "13,54,24" would both match a result of "127.0.0.24" from the rbl.
|
||||||
|
reply:
|
||||||
|
# 8/9/10/11 are all proxies
|
||||||
|
"8,9,10,11":
|
||||||
|
action: require-sasl
|
||||||
|
reason: "You need to enable SASL to access this network. For assistance, see http://dronebl.org/lookup?ip={ip}"
|
||||||
|
# 98 is an example reply type that's not real
|
||||||
|
98:
|
||||||
|
action: allow
|
||||||
|
|
||||||
|
-
|
||||||
|
host: "rbl.efnetrbl.org"
|
||||||
|
types:
|
||||||
|
- ipv4
|
||||||
|
action: block
|
||||||
|
reason: "Your IP ({ip}) is listed in the EFnet RBL. For assistance, see http://efnetrbl.org/?i={ip}"
|
||||||
|
|
||||||
|
-
|
||||||
|
host: "torexit.dan.me.uk"
|
||||||
|
types:
|
||||||
|
- ipv4
|
||||||
|
- ipv6
|
||||||
|
action: require-sasl
|
||||||
|
reason: "You need to enable SASL to access this network while using TOR"
|
||||||
|
Loading…
Reference in New Issue
Block a user