You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dnsbl.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package irc
  2. import (
  3. "fmt"
  4. "net"
  5. "sort"
  6. "strings"
  7. "github.com/oragono/oragono/irc/sno"
  8. "github.com/oragono/oragono/irc/utils"
  9. )
  10. // Constants
  11. type DnsblActionType uint
  12. const (
  13. DnsblRequireSaslReply DnsblActionType = iota
  14. DnsblAllowReply
  15. DnsblBlockReply
  16. DnsblNotifyReply
  17. DnsblUnknownReply
  18. )
  19. // LookupBlacklistEntry performs a lookup on the dnsbl on the client IP
  20. func (server *Server) LookupBlacklistEntry(list *DnsblListEntry, client *Client) []string {
  21. res, err := net.LookupHost(fmt.Sprintf("%s.%s", utils.ReverseAddress(client.IP()), list.Host))
  22. var entries []string
  23. if err != nil {
  24. // An error may indicate that the A record was not found
  25. return entries
  26. }
  27. if len(res) > 0 {
  28. for _, addr := range res {
  29. octet := strings.Split(addr, ".")
  30. if len(octet) > 0 {
  31. entries = append(entries, octet[len(octet)-1])
  32. }
  33. }
  34. }
  35. return entries
  36. }
  37. // ProcessBlacklist does
  38. func (server *Server) ProcessBlacklist(client *Client) {
  39. if !server.DnsblConfig().Enabled || len(server.DnsblConfig().Lists) == 0 {
  40. // do nothing if dnsbl is disabled, empty lists is treated as if dnsbl was disabled
  41. return
  42. }
  43. lists := server.DnsblConfig().Lists
  44. type DnsblTypeResponse struct {
  45. Host string
  46. ActionType DnsblActionType
  47. Reason string
  48. }
  49. var items = []DnsblTypeResponse{}
  50. for _, list := range lists {
  51. response := DnsblTypeResponse{
  52. Host: list.Host,
  53. ActionType: list.ActionType,
  54. Reason: list.Reason,
  55. }
  56. // update action/reason if matched with new ...
  57. for _, entry := range server.LookupBlacklistEntry(&list, client) {
  58. if reply, exists := list.Reply[entry]; exists {
  59. response.ActionType, response.Reason = list.ActionType, reply.Reason
  60. }
  61. items = append(items, response)
  62. }
  63. }
  64. // Sorts in the following order: require-sasl, allow, block, notify
  65. sort.Slice(items, func(i, j int) bool {
  66. return items[i].ActionType > items[j].ActionType
  67. })
  68. if len(items) > 0 {
  69. item := items[0]
  70. switch item.ActionType {
  71. case DnsblRequireSaslReply:
  72. dnsblSendServiceMessage(server, fmt.Sprintf("Connecting client %s matched %s, requiring SASL to proceed", client.IP(), item.Host))
  73. client.SetRequireSasl(true, item.Reason)
  74. case DnsblBlockReply:
  75. dnsblSendServiceMessage(server, fmt.Sprintf("Connecting client %s matched %s - killing", client.IP(), item.Host))
  76. client.Quit(strings.Replace(item.Reason, "{ip}", client.IPString(), -1))
  77. case DnsblNotifyReply:
  78. dnsblSendServiceMessage(server, fmt.Sprintf("Connecting client %s matched %s", client.IP(), item.Host))
  79. case DnsblAllowReply:
  80. dnsblSendServiceMessage(server, fmt.Sprintf("Allowing host %s [%s]", client.IP(), item.Host))
  81. }
  82. }
  83. return
  84. }
  85. func ConnectionRequiresSasl(client *Client) bool {
  86. sasl, reason := client.RequireSasl()
  87. if !sasl {
  88. return false
  89. }
  90. if client.Account() == "" {
  91. dnsblSendServiceMessage(client.server, fmt.Sprintf("Connecting client %s and did not authenticate through SASL - blocking connection", client.IP()))
  92. client.Quit(strings.Replace(reason, "{ip}", client.IPString(), -1))
  93. return true
  94. }
  95. dnsblSendServiceMessage(client.server, fmt.Sprintf("Connecting client %s authenticated through SASL - allowing", client.IP()))
  96. return false
  97. }
  98. func dnsblSendServiceMessage(server *Server, message string) {
  99. channel := server.DnsblConfig().Channel
  100. if channel != "" {
  101. server.serviceNotifyChannel(server.name, channel, message)
  102. }
  103. server.snomasks.Send(sno.Dnsbl, message)
  104. }