|
1 | 1 | package handlers |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "context" |
5 | | - "encoding/json" |
6 | | - "net" |
7 | 4 | "net/http" |
8 | | - "slices" |
9 | | - "sort" |
10 | | - "sync" |
11 | | - "time" |
12 | | -) |
13 | | - |
14 | | -type dnsServer struct { |
15 | | - Name string |
16 | | - IP string |
17 | | -} |
18 | | - |
19 | | -var DNS_SERVERS = []dnsServer{ |
20 | | - {Name: "AdGuard", IP: "176.103.130.130"}, |
21 | | - {Name: "AdGuard Family", IP: "176.103.130.132"}, |
22 | | - {Name: "CleanBrowsing Adult", IP: "185.228.168.10"}, |
23 | | - {Name: "CleanBrowsing Family", IP: "185.228.168.168"}, |
24 | | - {Name: "CleanBrowsing Security", IP: "185.228.168.9"}, |
25 | | - {Name: "CloudFlare", IP: "1.1.1.1"}, |
26 | | - {Name: "CloudFlare Family", IP: "1.1.1.3"}, |
27 | | - {Name: "Comodo Secure", IP: "8.26.56.26"}, |
28 | | - {Name: "Google DNS", IP: "8.8.8.8"}, |
29 | | - {Name: "Neustar Family", IP: "156.154.70.3"}, |
30 | | - {Name: "Neustar Protection", IP: "156.154.70.2"}, |
31 | | - {Name: "Norton Family", IP: "199.85.126.20"}, |
32 | | - {Name: "OpenDNS", IP: "208.67.222.222"}, |
33 | | - {Name: "OpenDNS Family", IP: "208.67.222.123"}, |
34 | | - {Name: "Quad9", IP: "9.9.9.9"}, |
35 | | - {Name: "Yandex Family", IP: "77.88.8.7"}, |
36 | | - {Name: "Yandex Safe", IP: "77.88.8.88"}, |
37 | | -} |
38 | | - |
39 | | -var knownBlockIPs = []string{ |
40 | | - "146.112.61.106", |
41 | | - "185.228.168.10", |
42 | | - "8.26.56.26", |
43 | | - "9.9.9.9", |
44 | | - "208.69.38.170", |
45 | | - "208.69.39.170", |
46 | | - "208.67.222.222", |
47 | | - "208.67.222.123", |
48 | | - "199.85.126.10", |
49 | | - "199.85.126.20", |
50 | | - "156.154.70.22", |
51 | | - "77.88.8.7", |
52 | | - "77.88.8.8", |
53 | | - "::1", |
54 | | - "2a02:6b8::feed:0ff", |
55 | | - "2a02:6b8::feed:bad", |
56 | | - "2a02:6b8::feed:a11", |
57 | | - "2620:119:35::35", |
58 | | - "2620:119:53::53", |
59 | | - "2606:4700:4700::1111", |
60 | | - "2606:4700:4700::1001", |
61 | | - "2001:4860:4860::8888", |
62 | | - "2a0d:2a00:1::", |
63 | | - "2a0d:2a00:2::", |
64 | | -} |
65 | | - |
66 | | -type Blocklist struct { |
67 | | - Server string `json:"server"` |
68 | | - ServerIP string `json:"serverIp"` |
69 | | - IsBlocked bool `json:"isBlocked"` |
70 | | -} |
71 | | - |
72 | | -func isDomainBlocked(domain, serverIP string) bool { |
73 | | - resolver := &net.Resolver{ |
74 | | - PreferGo: true, |
75 | | - Dial: func(ctx context.Context, network, address string) (net.Conn, error) { |
76 | | - d := net.Dialer{ |
77 | | - Timeout: time.Second * 3, |
78 | | - } |
79 | | - return d.DialContext(ctx, network, serverIP+":53") |
80 | | - }, |
81 | | - } |
82 | | - |
83 | | - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) |
84 | | - defer cancel() |
85 | 5 |
|
86 | | - ips, err := resolver.LookupIP(ctx, "ip4", domain) |
87 | | - if err != nil { |
88 | | - // if there's an error, consider it not blocked |
89 | | - return false |
90 | | - } |
91 | | - |
92 | | - return slices.ContainsFunc(ips, func(ip net.IP) bool { |
93 | | - return slices.Contains(knownBlockIPs, ip.String()) |
94 | | - }) |
95 | | -} |
96 | | - |
97 | | -func checkDomainAgainstDNSServers(domain string) []Blocklist { |
98 | | - var lock sync.Mutex |
99 | | - var wg sync.WaitGroup |
100 | | - limit := make(chan struct{}, 5) |
101 | | - |
102 | | - var results []Blocklist |
103 | | - |
104 | | - for _, server := range DNS_SERVERS { |
105 | | - wg.Add(1) |
106 | | - go func(server dnsServer) { |
107 | | - limit <- struct{}{} |
108 | | - defer func() { |
109 | | - <-limit |
110 | | - wg.Done() |
111 | | - }() |
112 | | - |
113 | | - isBlocked := isDomainBlocked(domain, server.IP) |
114 | | - lock.Lock() |
115 | | - defer lock.Unlock() |
116 | | - results = append(results, Blocklist{ |
117 | | - Server: server.Name, |
118 | | - ServerIP: server.IP, |
119 | | - IsBlocked: isBlocked, |
120 | | - }) |
121 | | - }(server) |
122 | | - } |
123 | | - wg.Wait() |
124 | | - |
125 | | - sort.Slice(results, func(i, j int) bool { |
126 | | - return results[i].Server > results[j].Server |
127 | | - }) |
128 | | - return results |
129 | | -} |
| 6 | + "github.com/xray-web/web-check-api/checks" |
| 7 | +) |
130 | 8 |
|
131 | | -func HandleBlockLists() http.Handler { |
132 | | - type Response struct { |
133 | | - BlockLists []Blocklist `json:"blocklists"` |
134 | | - } |
| 9 | +func HandleBlockLists(b *checks.BlockList) http.Handler { |
135 | 10 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
136 | 11 | rawURL, err := extractURL(r) |
137 | 12 | if err != nil { |
138 | 13 | JSONError(w, ErrMissingURLParameter, http.StatusBadRequest) |
139 | 14 | return |
140 | 15 | } |
141 | | - json.NewEncoder(w).Encode(Response{BlockLists: checkDomainAgainstDNSServers(rawURL.Hostname())}) |
| 16 | + list := b.BlockedServers(r.Context(), rawURL.Hostname()) |
| 17 | + JSON(w, list, http.StatusOK) |
142 | 18 | }) |
143 | 19 | } |
0 commit comments