private_address_check 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/private_address_check/version.rb +1 -1
- data/lib/private_address_check.rb +32 -8
- data/test/private_address_check_test.rb +50 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca4c176629d7fe2c0be2be0f113d51e0a03449cbf4c564387b7950f4500994a3
|
|
4
|
+
data.tar.gz: 1ca594143b83be4ebba2a0a5825b79bf81dfae0b015adbb5994d637a227d9c02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 95e99d25ee1a57352a61be412cae4505f968e958515e9ffa1fb79688f30a2e6c966cc61971111af1636e4abd7055fc3b2168c48d2c55311e77c1eaa7e99cc3a3
|
|
7
|
+
data.tar.gz: ad87ec9e56d459434ad6b9602807d67414bfa79fe9f6cddbab73a6158f3f95b837e6e16cb100c09e4ad87afbfa7119c4e6afbf825910fed98bd274a1d8367d88
|
|
@@ -7,10 +7,8 @@ module PrivateAddressCheck
|
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
9
|
# https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
|
|
10
|
-
|
|
11
|
-
CIDR_LIST = [
|
|
10
|
+
IPV4_CIDRS = [
|
|
12
11
|
IPAddr.new("127.0.0.0/8"), # Loopback
|
|
13
|
-
IPAddr.new("::1/128"), # Loopback
|
|
14
12
|
IPAddr.new("0.0.0.0/8"), # Current network (only valid as source address)
|
|
15
13
|
IPAddr.new("169.254.0.0/16"), # Link-local
|
|
16
14
|
IPAddr.new("10.0.0.0/8"), # Private network
|
|
@@ -18,26 +16,52 @@ module PrivateAddressCheck
|
|
|
18
16
|
IPAddr.new("172.16.0.0/12"), # Private network
|
|
19
17
|
IPAddr.new("192.0.0.0/24"), # IETF Protocol Assignments
|
|
20
18
|
IPAddr.new("192.0.2.0/24"), # TEST-NET-1, documentation and examples
|
|
21
|
-
IPAddr.new("192.88.99.0/24"), # IPv6 to IPv4 relay (
|
|
19
|
+
IPAddr.new("192.88.99.0/24"), # IPv6 to IPv4 relay anycast (RFC 7526, deprecated)
|
|
22
20
|
IPAddr.new("192.168.0.0/16"), # Private network
|
|
23
21
|
IPAddr.new("198.18.0.0/15"), # Network benchmark tests
|
|
24
22
|
IPAddr.new("198.51.100.0/24"), # TEST-NET-2, documentation and examples
|
|
25
23
|
IPAddr.new("203.0.113.0/24"), # TEST-NET-3, documentation and examples
|
|
26
24
|
IPAddr.new("224.0.0.0/4"), # IP multicast (former Class D network)
|
|
27
|
-
IPAddr.new("240.0.0.0/4")
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
IPAddr.new("240.0.0.0/4") # Reserved (former Class E network, covers 255.255.255.255)
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
# https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
|
|
29
|
+
IPV6_CIDRS = [
|
|
30
|
+
IPAddr.new("::/128"), # Unspecified address (RFC 4291)
|
|
31
|
+
IPAddr.new("::1/128"), # Loopback
|
|
32
|
+
IPAddr.new("64:ff9b:1::/48"), # IPv4/IPv6 translation, local use (RFC 8215)
|
|
30
33
|
IPAddr.new("100::/64"), # Discard prefix (RFC 6666)
|
|
34
|
+
IPAddr.new("100:0:0:1::/64"), # Dummy IPv6 Prefix (RFC 9780)
|
|
31
35
|
IPAddr.new("2001::/32"), # Teredo tunneling
|
|
36
|
+
IPAddr.new("2001:2::/48"), # Benchmarking (RFC 5180)
|
|
32
37
|
IPAddr.new("2001:10::/28"), # Deprecated (previously ORCHID)
|
|
33
38
|
IPAddr.new("2001:20::/28"), # ORCHIDv2
|
|
34
39
|
IPAddr.new("2001:db8::/32"), # Addresses used in documentation and example source code
|
|
35
|
-
IPAddr.new("
|
|
40
|
+
IPAddr.new("3fff::/20"), # Documentation (RFC 9637)
|
|
41
|
+
IPAddr.new("5f00::/16"), # Segment Routing (SRv6) SIDs (RFC 9602)
|
|
36
42
|
IPAddr.new("fc00::/7"), # Unique local address
|
|
37
43
|
IPAddr.new("fe80::/10"), # Link-local address
|
|
38
44
|
IPAddr.new("ff00::/8") # Multicast
|
|
39
45
|
].freeze
|
|
40
46
|
|
|
47
|
+
# Embedded IPv4 representations in IPv6, generated from IPV4_CIDRS so that
|
|
48
|
+
# addresses like ::ffff:10.0.0.1 cannot bypass the private-address check.
|
|
49
|
+
IPV4_MAPPED_CIDRS = IPV4_CIDRS.flat_map do |cidr|
|
|
50
|
+
prefix = cidr.prefix + 96
|
|
51
|
+
ip = cidr.to_s
|
|
52
|
+
octets = ip.split(".").map(&:to_i)
|
|
53
|
+
v4_hex = format("%<high>04x:%<low>04x", high: (octets[0] << 8) | octets[1], low: (octets[2] << 8) | octets[3])
|
|
54
|
+
[
|
|
55
|
+
IPAddr.new("::#{ip}/#{prefix}"), # IPv4-compatible (deprecated)
|
|
56
|
+
IPAddr.new("::ffff:#{ip}/#{prefix}"), # IPv4-mapped (RFC 4291)
|
|
57
|
+
IPAddr.new("::ffff:0:#{ip}/#{prefix}"), # IPv4-translated (RFC 2765)
|
|
58
|
+
IPAddr.new("64:ff9b::#{ip}/#{prefix}"), # NAT64 well-known prefix (RFC 6052)
|
|
59
|
+
IPAddr.new("2002:#{v4_hex}::/#{cidr.prefix + 16}") # 6to4 (RFC 3056)
|
|
60
|
+
]
|
|
61
|
+
end.freeze
|
|
62
|
+
|
|
63
|
+
CIDR_LIST = (IPV4_CIDRS + IPV6_CIDRS + IPV4_MAPPED_CIDRS).freeze
|
|
64
|
+
|
|
41
65
|
def private_address?(address)
|
|
42
66
|
CIDR_LIST.any? do |cidr|
|
|
43
67
|
cidr.include?(address)
|
|
@@ -27,6 +27,56 @@ class PrivateAddressCheckTest < Minitest::Test
|
|
|
27
27
|
assert PrivateAddressCheck.private_address?("169.254.2.5")
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def test_private_address_for_unspecified_ipv6
|
|
31
|
+
assert PrivateAddressCheck.private_address?("::")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_private_address_for_additional_ipv6_special_ranges
|
|
35
|
+
assert PrivateAddressCheck.private_address?("64:ff9b:1::1")
|
|
36
|
+
assert PrivateAddressCheck.private_address?("2001:2::1")
|
|
37
|
+
assert PrivateAddressCheck.private_address?("3fff::1")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_private_address_for_dummy_ipv6_prefix
|
|
41
|
+
assert PrivateAddressCheck.private_address?("100:0:0:1::1")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_private_address_for_srv6_sid_range
|
|
45
|
+
assert PrivateAddressCheck.private_address?("5f00::1")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_private_address_for_ipv4_mapped_ipv6_addresses
|
|
49
|
+
assert PrivateAddressCheck.private_address?("::ffff:127.0.0.1")
|
|
50
|
+
assert PrivateAddressCheck.private_address?("::ffff:10.0.0.1")
|
|
51
|
+
assert PrivateAddressCheck.private_address?("::ffff:169.254.169.254")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_private_address_for_alternate_ipv4_embeddings
|
|
55
|
+
assert PrivateAddressCheck.private_address?("::127.0.0.1")
|
|
56
|
+
assert PrivateAddressCheck.private_address?("::ffff:0:127.0.0.1")
|
|
57
|
+
assert PrivateAddressCheck.private_address?("64:ff9b::127.0.0.1")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_public_ipv4_mapped_ipv6_addresses_are_not_private
|
|
61
|
+
refute PrivateAddressCheck.private_address?("::ffff:8.8.8.8")
|
|
62
|
+
refute PrivateAddressCheck.private_address?("::ffff:1.1.1.1")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def test_public_nat64_and_6to4_addresses_are_not_private
|
|
66
|
+
refute PrivateAddressCheck.private_address?("64:ff9b::8.8.8.8")
|
|
67
|
+
refute PrivateAddressCheck.private_address?("2002:808:808::1")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_private_nat64_addresses_are_still_private
|
|
71
|
+
assert PrivateAddressCheck.private_address?("64:ff9b::10.0.0.1")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_private_6to4_addresses_are_private
|
|
75
|
+
assert PrivateAddressCheck.private_address?("2002:0a00:0001::1")
|
|
76
|
+
assert PrivateAddressCheck.private_address?("2002:7f00:0001::1")
|
|
77
|
+
assert PrivateAddressCheck.private_address?("2002:a9fe:a9fe::1")
|
|
78
|
+
end
|
|
79
|
+
|
|
30
80
|
def test_private_hostname_for_public_addresses
|
|
31
81
|
refute PrivateAddressCheck.resolves_to_private_address?("github.com")
|
|
32
82
|
refute PrivateAddressCheck.resolves_to_private_address?("example.com")
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: private_address_check
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Downey
|
|
@@ -46,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '0'
|
|
48
48
|
requirements: []
|
|
49
|
-
rubygems_version: 4.0.
|
|
49
|
+
rubygems_version: 4.0.10
|
|
50
50
|
specification_version: 4
|
|
51
51
|
summary: Prevent Server Side Request Forgery attacks by checking the destination
|
|
52
52
|
test_files: []
|