From 56f13a9ae1ca8cc93e42ef7cd239611b99c54d2d Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 09:42:16 +0100 Subject: [PATCH 01/10] created IsInternal functions for ipv4 and ipv6 --- ip/iputil.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/ip/iputil.go b/ip/iputil.go index 52f92a5..02ef7d5 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -14,6 +14,51 @@ import ( "go.uber.org/multierr" ) +var ipv4InternalRanges = []string{} +var ipv6InternalRanges = []string{} + +// internalRangeChecker contains a list of internal IP ranges. +type internalRangeChecker struct { + ipv4 []*net.IPNet + ipv6 []*net.IPNet +} + +func init() { + // ipv4InternalRanges contains the IP ranges internal in IPv4 range. + ipv4InternalRanges = []string{ + "0.0.0.0/8", // Current network (only valid as source address) + "10.0.0.0/8", // Private network + "100.64.0.0/10", // Shared Address Space + "127.0.0.0/8", // Loopback + "169.254.0.0/16", // Link-local (Also many cloud providers Metadata endpoint) + "172.16.0.0/12", // Private network + "192.0.0.0/24", // IETF Protocol Assignments + "192.0.2.0/24", // TEST-NET-1, documentation and examples + "192.88.99.0/24", // IPv6 to IPv4 relay (includes 2002::/16) + "192.168.0.0/16", // Private network + "198.18.0.0/15", // Network benchmark tests + "198.51.100.0/24", // TEST-NET-2, documentation and examples + "203.0.113.0/24", // TEST-NET-3, documentation and examples + "224.0.0.0/4", // IP multicast (former Class D network) + "240.0.0.0/4", // Reserved (former Class E network) + } + + // ipv6InternalRanges contains the IP ranges internal in IPv6 range. + ipv6InternalRanges = []string{ + "::1/128", // Loopback + "64:ff9b::/96", // IPv4/IPv6 translation (RFC 6052) + "100::/64", // Discard prefix (RFC 6666) + "2001::/32", // Teredo tunneling + "2001:10::/28", // Deprecated (previously ORCHID) + "2001:20::/28", // ORCHIDv2 + "2001:db8::/32", // Addresses used in documentation and example source code + "2002::/16", // 6to4 + "fc00::/7", // Unique local address + "fe80::/10", // Link-local address + "ff00::/8", // Multicast + } +} + // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` func IsIP(str string) bool { return net.ParseIP(str) != nil @@ -48,6 +93,26 @@ func IsIPv4(ips ...interface{}) bool { return true } +// Check if an IP address is part of the list of internal IPs we have declared +func IsInternalIpv4(str string) bool { + for _, ip := range ipv4InternalRanges { + if strings.Contains(ip, str) { + return true + } + } + return false +} + +// Check if an IP address is part of the list of internal IPs we have declared +func IsInternalIpv6(str string) bool { + for _, ip := range ipv6InternalRanges { + if strings.Contains(ip, str) { + return true + } + } + return false +} + // IsIPv6 checks if the string is an IP version 6. func IsIPv6(ips ...interface{}) bool { for _, ip := range ips { From d3687f4ebb0e57830722caefa6e9524baa7d576d Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 09:48:25 +0100 Subject: [PATCH 02/10] removed unused struct --- ip/iputil.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index 02ef7d5..03084a2 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -17,12 +17,6 @@ import ( var ipv4InternalRanges = []string{} var ipv6InternalRanges = []string{} -// internalRangeChecker contains a list of internal IP ranges. -type internalRangeChecker struct { - ipv4 []*net.IPNet - ipv6 []*net.IPNet -} - func init() { // ipv4InternalRanges contains the IP ranges internal in IPv4 range. ipv4InternalRanges = []string{ From d5463152566244b0079a2e234508327c71898281 Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 10:58:14 +0100 Subject: [PATCH 03/10] better login on IsInternal function --- ip/iputil.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ip/iputil.go b/ip/iputil.go index 03084a2..b1d370f 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -17,6 +17,14 @@ import ( var ipv4InternalRanges = []string{} var ipv6InternalRanges = []string{} +// internalRangeChecker contains a list of internal IP ranges. +type internalRangeChecker struct { + ipv4 []*net.IPNet + ipv6 []*net.IPNet +} + +var rangeChecker = internalRangeChecker{} + func init() { // ipv4InternalRanges contains the IP ranges internal in IPv4 range. ipv4InternalRanges = []string{ @@ -51,6 +59,8 @@ func init() { "fe80::/10", // Link-local address "ff00::/8", // Multicast } + + newInternalRangeChecker() } // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` @@ -87,6 +97,27 @@ func IsIPv4(ips ...interface{}) bool { return true } +// Check if an IP address is part of the list of internal IPs we have declared +// checks for all ipv4 and ipv6 list +func IsInternal(str string) bool { + if !IsIP(str) { + return false + + } + IP := net.ParseIP(str) + for _, net := range rangeChecker.ipv4 { + if net.Contains(IP) { + return true + } + } + for _, net := range rangeChecker.ipv6 { + if net.Contains(IP) { + return true + } + } + return false +} + // Check if an IP address is part of the list of internal IPs we have declared func IsInternalIpv4(str string) bool { for _, ip := range ipv4InternalRanges { @@ -277,3 +308,42 @@ func GetBindableAddress(port int, ips ...string) (string, error) { return "", errs } + +// newInternalRangeChecker creates a structure for checking if a host is from +// a internal IP range whether its ipv4 or ipv6. +func newInternalRangeChecker() (*internalRangeChecker, error) { + err := rangeChecker.appendIPv4Ranges(ipv4InternalRanges) + if err != nil { + return nil, err + } + + err = rangeChecker.appendIPv6Ranges(ipv6InternalRanges) + if err != nil { + return nil, err + } + return &rangeChecker, nil +} + +// appendIPv4Ranges adds a list of IPv4 Ranges to the list. +func (r *internalRangeChecker) appendIPv4Ranges(ranges []string) error { + for _, ip := range ranges { + _, rangeNet, err := net.ParseCIDR(ip) + if err != nil { + return err + } + r.ipv4 = append(r.ipv4, rangeNet) + } + return nil +} + +// appendIPv6Ranges adds a list of IPv6 Ranges to the list. +func (r *internalRangeChecker) appendIPv6Ranges(ranges []string) error { + for _, ip := range ranges { + _, rangeNet, err := net.ParseCIDR(ip) + if err != nil { + return err + } + r.ipv6 = append(r.ipv6, rangeNet) + } + return nil +} From c4d0ea10b18f424844d78881eecd8a97f2d84e86 Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 11:08:21 +0100 Subject: [PATCH 04/10] unit tests on IsInternal function --- ip/iputil_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ip/iputil_test.go b/ip/iputil_test.go index 1a2eccb..ff3ba22 100644 --- a/ip/iputil_test.go +++ b/ip/iputil_test.go @@ -12,6 +12,15 @@ func TestIsIP(t *testing.T) { require.False(t, IsIP("test"), "string recognized as ip") } +func TestIsInternalIPv4(t *testing.T) { + // Test this ipv4 + require.False(t, IsInternal("153.12.14.1"), "internal ipv4 address recognized as not valid") + require.True(t, IsInternal("172.16.0.0"), "internal ipv4 address recognized as valid") + // Test with ipv6 + require.False(t, IsInternal("684D:1111:222:3333:4444:5555:6:77"), "internal ipv4 address recognized as not valid") + require.True(t, IsInternal("fc00:7e5b:cfa9::"), "internal ipv4 address recognized as valid") +} + func TestIsPort(t *testing.T) { require.False(t, IsPort("0"), "invalid port 0") require.False(t, IsPort("-1"), "negative port") From 4ef810c8272669e382eaeb97689c1d26855a978e Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 11:22:03 +0100 Subject: [PATCH 05/10] fix + error check --- ip/iputil.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index b1d370f..bff0dd0 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -59,8 +59,6 @@ func init() { "fe80::/10", // Link-local address "ff00::/8", // Multicast } - - newInternalRangeChecker() } // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` @@ -100,6 +98,11 @@ func IsIPv4(ips ...interface{}) bool { // Check if an IP address is part of the list of internal IPs we have declared // checks for all ipv4 and ipv6 list func IsInternal(str string) bool { + _, err := newInternalRangeChecker() + if err != nil { + return false + } + if !IsIP(str) { return false From 95b9ac4f9e855bf8d0e4cd7b84af3f190347d00d Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 14:06:03 +0100 Subject: [PATCH 06/10] fixes, better var declaration --- ip/iputil.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index bff0dd0..5b1ea46 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "log" "net" "net/http" "strconv" @@ -14,16 +15,17 @@ import ( "go.uber.org/multierr" ) -var ipv4InternalRanges = []string{} -var ipv6InternalRanges = []string{} - // internalRangeChecker contains a list of internal IP ranges. type internalRangeChecker struct { ipv4 []*net.IPNet ipv6 []*net.IPNet } -var rangeChecker = internalRangeChecker{} +var ( + ipv4InternalRanges = []string{} + ipv6InternalRanges = []string{} + rangeChecker = internalRangeChecker{} +) func init() { // ipv4InternalRanges contains the IP ranges internal in IPv4 range. @@ -59,6 +61,11 @@ func init() { "fe80::/10", // Link-local address "ff00::/8", // Multicast } + + _, err := newInternalRangeChecker() + if err != nil { + log.Fatal(err) + } } // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` @@ -98,11 +105,6 @@ func IsIPv4(ips ...interface{}) bool { // Check if an IP address is part of the list of internal IPs we have declared // checks for all ipv4 and ipv6 list func IsInternal(str string) bool { - _, err := newInternalRangeChecker() - if err != nil { - return false - } - if !IsIP(str) { return false @@ -122,7 +124,7 @@ func IsInternal(str string) bool { } // Check if an IP address is part of the list of internal IPs we have declared -func IsInternalIpv4(str string) bool { +func IsInIpv4List(str string) bool { for _, ip := range ipv4InternalRanges { if strings.Contains(ip, str) { return true @@ -132,7 +134,7 @@ func IsInternalIpv4(str string) bool { } // Check if an IP address is part of the list of internal IPs we have declared -func IsInternalIpv6(str string) bool { +func IsInIpv6List(str string) bool { for _, ip := range ipv6InternalRanges { if strings.Contains(ip, str) { return true From 9bbadac40c0dd4333e6877365883b7c2edd3e2a5 Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 14:10:39 +0100 Subject: [PATCH 07/10] used panic instead of log.Fatal --- ip/iputil.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index 5b1ea46..78552a0 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "log" "net" "net/http" "strconv" @@ -64,7 +63,7 @@ func init() { _, err := newInternalRangeChecker() if err != nil { - log.Fatal(err) + panic(err) } } From 0ee23aee02dd863078726b983033747b24046bc3 Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 14:25:08 +0100 Subject: [PATCH 08/10] used log.Fatal, dont create problems with mac action on build --- ip/iputil.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ip/iputil.go b/ip/iputil.go index 78552a0..5b1ea46 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "log" "net" "net/http" "strconv" @@ -63,7 +64,7 @@ func init() { _, err := newInternalRangeChecker() if err != nil { - panic(err) + log.Fatal(err) } } From 6ba87722b7ba31cef528d6448a054e5adcdc231a Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 16:32:20 +0100 Subject: [PATCH 09/10] better implementation on isInternal logic --- ip/iputil.go | 80 +++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 57 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index 5b1ea46..12df8ad 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "log" "net" "net/http" "strconv" @@ -15,19 +14,7 @@ import ( "go.uber.org/multierr" ) -// internalRangeChecker contains a list of internal IP ranges. -type internalRangeChecker struct { - ipv4 []*net.IPNet - ipv6 []*net.IPNet -} - var ( - ipv4InternalRanges = []string{} - ipv6InternalRanges = []string{} - rangeChecker = internalRangeChecker{} -) - -func init() { // ipv4InternalRanges contains the IP ranges internal in IPv4 range. ipv4InternalRanges = []string{ "0.0.0.0/8", // Current network (only valid as source address) @@ -62,10 +49,28 @@ func init() { "ff00::/8", // Multicast } - _, err := newInternalRangeChecker() - if err != nil { - log.Fatal(err) + ipv4, ipv6 []*net.IPNet +) + +func init() { + for _, cidr := range ipv4InternalRanges { + _, rangeNet, err := net.ParseCIDR(cidr) + if err != nil { + panic(err) + } + ipv4 = append(ipv4, rangeNet) + } + + for _, cidr := range ipv6InternalRanges { + _, rangeNet, err := net.ParseCIDR(cidr) + if err != nil { + panic(err) + } + ipv6 = append(ipv6, rangeNet) } + + fmt.Println("ipv4", ipv4) + fmt.Println("ipv6", ipv6) } // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP` @@ -110,12 +115,12 @@ func IsInternal(str string) bool { } IP := net.ParseIP(str) - for _, net := range rangeChecker.ipv4 { + for _, net := range ipv4 { if net.Contains(IP) { return true } } - for _, net := range rangeChecker.ipv6 { + for _, net := range ipv6 { if net.Contains(IP) { return true } @@ -313,42 +318,3 @@ func GetBindableAddress(port int, ips ...string) (string, error) { return "", errs } - -// newInternalRangeChecker creates a structure for checking if a host is from -// a internal IP range whether its ipv4 or ipv6. -func newInternalRangeChecker() (*internalRangeChecker, error) { - err := rangeChecker.appendIPv4Ranges(ipv4InternalRanges) - if err != nil { - return nil, err - } - - err = rangeChecker.appendIPv6Ranges(ipv6InternalRanges) - if err != nil { - return nil, err - } - return &rangeChecker, nil -} - -// appendIPv4Ranges adds a list of IPv4 Ranges to the list. -func (r *internalRangeChecker) appendIPv4Ranges(ranges []string) error { - for _, ip := range ranges { - _, rangeNet, err := net.ParseCIDR(ip) - if err != nil { - return err - } - r.ipv4 = append(r.ipv4, rangeNet) - } - return nil -} - -// appendIPv6Ranges adds a list of IPv6 Ranges to the list. -func (r *internalRangeChecker) appendIPv6Ranges(ranges []string) error { - for _, ip := range ranges { - _, rangeNet, err := net.ParseCIDR(ip) - if err != nil { - return err - } - r.ipv6 = append(r.ipv6, rangeNet) - } - return nil -} From 846210ab641f691a059f9abf6fba43adceb29878 Mon Sep 17 00:00:00 2001 From: xm1k3 Date: Mon, 14 Nov 2022 19:36:31 +0100 Subject: [PATCH 10/10] removed debug instructions --- ip/iputil.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/ip/iputil.go b/ip/iputil.go index 12df8ad..3e09814 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -68,9 +68,6 @@ func init() { } ipv6 = append(ipv6, rangeNet) } - - fmt.Println("ipv4", ipv4) - fmt.Println("ipv6", ipv6) } // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP`