github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/util/net/firewall_dialer.go (about) 1 package net 2 3 import ( 4 "context" 5 "net" 6 "syscall" 7 8 "github.com/grafana/dskit/flagext" 9 "github.com/pkg/errors" 10 ) 11 12 var errBlockedAddress = errors.New("blocked address") 13 var errInvalidAddress = errors.New("invalid address") 14 15 type FirewallDialerConfigProvider interface { 16 BlockCIDRNetworks() []flagext.CIDR 17 BlockPrivateAddresses() bool 18 } 19 20 // FirewallDialer is a net dialer which integrates a firewall to block specific addresses. 21 type FirewallDialer struct { 22 parent *net.Dialer 23 cfgProvider FirewallDialerConfigProvider 24 } 25 26 func NewFirewallDialer(cfgProvider FirewallDialerConfigProvider) *FirewallDialer { 27 d := &FirewallDialer{cfgProvider: cfgProvider} 28 d.parent = &net.Dialer{Control: d.control} 29 return d 30 } 31 32 func (d *FirewallDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { 33 return d.parent.DialContext(ctx, network, address) 34 } 35 36 func (d *FirewallDialer) control(_, address string, _ syscall.RawConn) error { 37 blockPrivateAddresses := d.cfgProvider.BlockPrivateAddresses() 38 blockCIDRNetworks := d.cfgProvider.BlockCIDRNetworks() 39 40 // Skip any control if no firewall has been configured. 41 if !blockPrivateAddresses && len(blockCIDRNetworks) == 0 { 42 return nil 43 } 44 45 host, _, err := net.SplitHostPort(address) 46 if err != nil { 47 return errInvalidAddress 48 } 49 50 // We expect an IP as address because the DNS resolution already occurred. 51 ip := net.ParseIP(host) 52 if ip == nil { 53 return errBlockedAddress 54 } 55 56 if blockPrivateAddresses && (isPrivate(ip) || isLocal(ip)) { 57 return errBlockedAddress 58 } 59 60 for _, cidr := range blockCIDRNetworks { 61 if cidr.Value.Contains(ip) { 62 return errBlockedAddress 63 } 64 } 65 66 return nil 67 } 68 69 func isLocal(ip net.IP) bool { 70 return ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() 71 } 72 73 // isPrivate reports whether ip is a private address, according to 74 // RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses). 75 // 76 // This function has been copied from golang and should be removed once 77 // we'll upgrade to go 1.17. See: https://github.com/golang/go/pull/42793 78 func isPrivate(ip net.IP) bool { 79 if ip4 := ip.To4(); ip4 != nil { 80 // Following RFC 4193, Section 3. Local IPv6 Unicast Addresses which says: 81 // The Internet Assigned Numbers Authority (IANA) has reserved the 82 // following three blocks of the IPv4 address space for private internets: 83 // 10.0.0.0 - 10.255.255.255 (10/8 prefix) 84 // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) 85 // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) 86 return ip4[0] == 10 || 87 (ip4[0] == 172 && ip4[1]&0xf0 == 16) || 88 (ip4[0] == 192 && ip4[1] == 168) 89 } 90 // Following RFC 4193, Section 3. Private Address Space which says: 91 // The Internet Assigned Numbers Authority (IANA) has reserved the 92 // following block of the IPv6 address space for local internets: 93 // FC00:: - FDFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF (FC00::/7 prefix) 94 return len(ip) == net.IPv6len && ip[0]&0xfe == 0xfc 95 }