66import okhttp3 .OkHttpClient ;
77import okhttp3 .Request ;
88import okhttp3 .Response ;
9+ import java .net .InetAddress ;
10+ import java .net .UnknownHostException ;
911
1012public class IPRequest extends BaseRequest <IPResponse > {
1113 private final static String URL_FORMAT = "https://ipinfo.io/%s" ;
@@ -18,6 +20,14 @@ public IPRequest(OkHttpClient client, String token, String ip) {
1820
1921 @ Override
2022 public IPResponse handle () throws RateLimitedException {
23+ if (isBogon (ip )) {
24+ try {
25+ return new IPResponse (ip , true );
26+ } catch (Exception ex ) {
27+ throw new ErrorResponseException (ex );
28+ }
29+ }
30+
2131 String url = String .format (URL_FORMAT , ip );
2232 Request .Builder request = new Request .Builder ().url (url ).get ();
2333
@@ -33,4 +43,147 @@ public IPResponse handle() throws RateLimitedException {
3343 }
3444 }
3545 }
46+
47+ static IpAddressMatcher [] IpAddressMatcherList = {
48+ // IPv4
49+ new IpAddressMatcher ("0.0.0.0/8" ),
50+ new IpAddressMatcher ("10.0.0.0/8" ),
51+ new IpAddressMatcher ("100.64.0.0/10" ),
52+ new IpAddressMatcher ("127.0.0.0/8" ),
53+ new IpAddressMatcher ("169.254.0.0/16" ),
54+ new IpAddressMatcher ("172.16.0.0/12" ),
55+ new IpAddressMatcher ("192.0.0.0/24" ),
56+ new IpAddressMatcher ("192.0.2.0/24" ),
57+ new IpAddressMatcher ("192.168.0.0/16" ),
58+ new IpAddressMatcher ("198.18.0.0/15" ),
59+ new IpAddressMatcher ("198.51.100.0/24" ),
60+ new IpAddressMatcher ("203.0.113.0/24" ),
61+ new IpAddressMatcher ("224.0.0.0/4" ),
62+ new IpAddressMatcher ("240.0.0.0/4" ),
63+ new IpAddressMatcher ("255.255.255.255/32" ),
64+ // IPv6
65+ new IpAddressMatcher ("::/128" ),
66+ new IpAddressMatcher ("::1/128" ),
67+ new IpAddressMatcher ("::ffff:0:0/96" ),
68+ new IpAddressMatcher ("::/96" ),
69+ new IpAddressMatcher ("100::/64" ),
70+ new IpAddressMatcher ("2001:10::/28" ),
71+ new IpAddressMatcher ("2001:db8::/32" ),
72+ new IpAddressMatcher ("fc00::/7" ),
73+ new IpAddressMatcher ("fe80::/10" ),
74+ new IpAddressMatcher ("fec0::/10" ),
75+ new IpAddressMatcher ("ff00::/8" ),
76+ // 6to4
77+ new IpAddressMatcher ("2002::/24" ),
78+ new IpAddressMatcher ("2002:a00::/24" ),
79+ new IpAddressMatcher ("2002:7f00::/24" ),
80+ new IpAddressMatcher ("2002:a9fe::/32" ),
81+ new IpAddressMatcher ("2002:ac10::/28" ),
82+ new IpAddressMatcher ("2002:c000::/40" ),
83+ new IpAddressMatcher ("2002:c000:200::/40" ),
84+ new IpAddressMatcher ("2002:c0a8::/32" ),
85+ new IpAddressMatcher ("2002:c612::/31" ),
86+ new IpAddressMatcher ("2002:c633:6400::/40" ),
87+ new IpAddressMatcher ("2002:cb00:7100::/40" ),
88+ new IpAddressMatcher ("2002:e000::/20" ),
89+ new IpAddressMatcher ("2002:f000::/20" ),
90+ new IpAddressMatcher ("2002:ffff:ffff::/48" ),
91+ // Teredo
92+ new IpAddressMatcher ("2001::/40" ),
93+ new IpAddressMatcher ("2001:0:a00::/40" ),
94+ new IpAddressMatcher ("2001:0:7f00::/40" ),
95+ new IpAddressMatcher ("2001:0:a9fe::/48" ),
96+ new IpAddressMatcher ("2001:0:ac10::/44" ),
97+ new IpAddressMatcher ("2001:0:c000::/56" ),
98+ new IpAddressMatcher ("2001:0:c000:200::/56" ),
99+ new IpAddressMatcher ("2001:0:c0a8::/48" ),
100+ new IpAddressMatcher ("2001:0:c612::/47" ),
101+ new IpAddressMatcher ("2001:0:c633:6400::/56" ),
102+ new IpAddressMatcher ("2001:0:cb00:7100::/56" ),
103+ new IpAddressMatcher ("2001:0:e000::/36" ),
104+ new IpAddressMatcher ("2001:0:f000::/36" ),
105+ new IpAddressMatcher ("2001:0:ffff:ffff::/64" )
106+ };
107+
108+ static boolean isBogon (String ip ) {
109+ for (int i = 0 ; i < IpAddressMatcherList .length ; i ++) {
110+ IpAddressMatcher ipAddressMatcher = IpAddressMatcherList [i ];
111+ if (ipAddressMatcher .matches (ip )) {
112+ return true ;
113+ }
114+ }
115+ return false ;
116+ }
117+
118+ static InetAddress parseAddress (String address ) {
119+ try {
120+ return InetAddress .getByName (address );
121+ }
122+ catch (UnknownHostException e ) {
123+ throw new IllegalArgumentException ("Failed to parse address: " + address , e );
124+ }
125+ }
126+
127+ /*
128+ * Copyright 2002-2019 the original author or authors.
129+ *
130+ * Licensed under the Apache License, Version 2.0 (the "License");
131+ * you may not use this file except in compliance with the License.
132+ * You may obtain a copy of the License at
133+ *
134+ * https://www.apache.org/licenses/LICENSE-2.0
135+ *
136+ * Unless required by applicable law or agreed to in writing, software
137+ * distributed under the License is distributed on an "AS IS" BASIS,
138+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139+ * See the License for the specific language governing permissions and
140+ * limitations under the License.
141+ */
142+ public static class IpAddressMatcher {
143+ private final int nMaskBits ;
144+ private final InetAddress requiredAddress ;
145+
146+ public IpAddressMatcher (String ipAddress ) {
147+
148+ if (ipAddress .indexOf ('/' ) > 0 ) {
149+ String [] addressAndMask = ipAddress .split ("/" );
150+ ipAddress = addressAndMask [0 ];
151+ nMaskBits = Integer .parseInt (addressAndMask [1 ]);
152+ }
153+ else {
154+ nMaskBits = -1 ;
155+ }
156+ requiredAddress = parseAddress (ipAddress );
157+ }
158+
159+ public boolean matches (String address ) {
160+ InetAddress remoteAddress = parseAddress (address );
161+
162+ if (!requiredAddress .getClass ().equals (remoteAddress .getClass ())) {
163+ return false ;
164+ }
165+
166+ if (nMaskBits < 0 ) {
167+ return remoteAddress .equals (requiredAddress );
168+ }
169+
170+ byte [] remAddr = remoteAddress .getAddress ();
171+ byte [] reqAddr = requiredAddress .getAddress ();
172+
173+ int nMaskFullBytes = nMaskBits / 8 ;
174+ byte finalByte = (byte ) (0xFF00 >> (nMaskBits & 0x07 ));
175+
176+ for (int i = 0 ; i < nMaskFullBytes ; i ++) {
177+ if (remAddr [i ] != reqAddr [i ]) {
178+ return false ;
179+ }
180+ }
181+
182+ if (finalByte != 0 ) {
183+ return (remAddr [nMaskFullBytes ] & finalByte ) == (reqAddr [nMaskFullBytes ] & finalByte );
184+ }
185+
186+ return true ;
187+ }
188+ }
36189}
0 commit comments