1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// Copyright 2022 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package netutil
import (
"fmt"
"net"
)
var localCIDRs []*net.IPNet
func init() {
// Parsing hardcoded CIDR strings should never fail, if in case it does, let's
// fail it at start.
rawCIDRs := []string{
// https://datatracker.ietf.org/doc/html/rfc5735:
"127.0.0.0/8", // Loopback
"0.0.0.0/8", // "This" network
"100.64.0.0/10", // Shared address space
"169.254.0.0/16", // Link local
"172.16.0.0/12", // Private-use networks
"192.0.0.0/24", // IETF Protocol assignments
"192.0.2.0/24", // TEST-NET-1
"192.88.99.0/24", // 6to4 Relay anycast
"192.168.0.0/16", // Private-use networks
"198.18.0.0/15", // Network interconnect
"198.51.100.0/24", // TEST-NET-2
"203.0.113.0/24", // TEST-NET-3
"255.255.255.255/32", // Limited broadcast
// https://datatracker.ietf.org/doc/html/rfc1918:
"10.0.0.0/8", // Private-use networks
// https://datatracker.ietf.org/doc/html/rfc6890:
"::1/128", // Loopback
"FC00::/7", // Unique local address
"FE80::/10", // Multicast address
}
for _, raw := range rawCIDRs {
_, cidr, err := net.ParseCIDR(raw)
if err != nil {
panic(fmt.Sprintf("parse CIDR %q: %v", raw, err))
}
localCIDRs = append(localCIDRs, cidr)
}
}
// IsBlockedLocalHostname returns true if given hostname is resolved to a local
// network address that is implicitly blocked (i.e. not exempted from the
// allowlist).
func IsBlockedLocalHostname(hostname string, allowlist []string) bool {
for _, allow := range allowlist {
if hostname == allow || allow == "*" {
return false
}
}
ips, err := net.LookupIP(hostname)
if err != nil {
return true
}
for _, ip := range ips {
for _, cidr := range localCIDRs {
if cidr.Contains(ip) {
return true
}
}
}
return false
}
|