vpndetection-fastapi 2.0.6__tar.gz → 2.0.8__tar.gz

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.
@@ -2,6 +2,18 @@
2
2
 
3
3
  What each release changed for you, newest first. Each line is a commit's summary, linked to its full description and diff. Releases before 2.0.5 are described by their release commits.
4
4
 
5
+ ## 2.0.8 - 2026-09-29
6
+
7
+ ### Fixes
8
+
9
+ - Require vpndetection 5.5.2: 26 more reserved ranges are answered locally ([`73b34b6`](https://github.com/vpndetection-io/sdk-python-fastapi/commit/73b34b6ca355cc56fcfcbf159a241ec114541c78))
10
+
11
+ ## 2.0.7 - 2026-09-28
12
+
13
+ ### Fixes
14
+
15
+ - Require vpndetection 5.5.1: IPv4-mapped visitors are looked up, not waved through ([`976dc44`](https://github.com/vpndetection-io/sdk-python-fastapi/commit/976dc44ca5a65d2a13d6ce1d366a4582de24db89))
16
+
5
17
  ## 2.0.6 - 2026-09-27
6
18
 
7
19
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vpndetection-fastapi
3
- Version: 2.0.6
3
+ Version: 2.0.8
4
4
  Summary: Official FastAPI and Starlette middleware for the VPNDetection API. Detect VPNs, proxies, Tor, hosting and CDN visitors on every request.
5
5
  Project-URL: Homepage, https://vpndetection.io
6
6
  Project-URL: Source, https://github.com/vpndetection-io/sdk-python-fastapi
@@ -20,7 +20,7 @@ Classifier: Topic :: Security
20
20
  Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.11
22
22
  Requires-Dist: starlette>=0.37
23
- Requires-Dist: vpndetection<6,>=5.5.0
23
+ Requires-Dist: vpndetection<6,>=5.5.2
24
24
  Provides-Extra: dev
25
25
  Requires-Dist: mypy>=1.11; extra == 'dev'
26
26
  Requires-Dist: pytest>=8; extra == 'dev'
@@ -124,7 +124,7 @@ Skip what you do not care about:
124
124
  skip = lambda request: request.url.path.startswith("/static")
125
125
  ```
126
126
 
127
- Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/databases) and look addresses up locally instead.
127
+ Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/#databases) and look addresses up locally instead.
128
128
 
129
129
  ## Absent is not false
130
130
 
@@ -95,7 +95,7 @@ Skip what you do not care about:
95
95
  skip = lambda request: request.url.path.startswith("/static")
96
96
  ```
97
97
 
98
- Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/databases) and look addresses up locally instead.
98
+ Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/#databases) and look addresses up locally instead.
99
99
 
100
100
  ## Absent is not false
101
101
 
@@ -24,7 +24,7 @@ classifiers = [
24
24
  "Topic :: Security",
25
25
  "Typing :: Typed",
26
26
  ]
27
- dependencies = ["vpndetection>=5.5.0,<6", "starlette>=0.37"]
27
+ dependencies = ["vpndetection>=5.5.2,<6", "starlette>=0.37"]
28
28
 
29
29
  [project.urls]
30
30
  Homepage = "https://vpndetection.io"
@@ -39,7 +39,7 @@ __all__ = [
39
39
  "xff_ip_selector",
40
40
  ]
41
41
 
42
- __version__ = "2.0.6"
42
+ __version__ = "2.0.8"
43
43
 
44
44
  _SELECTORS: Selectors[Request] = bind_selectors(
45
45
  lambda request: RequestView(
@@ -8,53 +8,79 @@
8
8
  "172.16.0.0/12",
9
9
  "192.0.0.0/24",
10
10
  "192.0.2.0/24",
11
+ "192.88.99.2/32",
11
12
  "192.168.0.0/16",
12
13
  "198.18.0.0/15",
13
14
  "198.51.100.0/24",
14
15
  "203.0.113.0/24",
15
16
  "224.0.0.0/4",
16
- "240.0.0.0/4",
17
- "255.255.255.255/32"
17
+ "255.255.255.255/32",
18
+ "240.0.0.0/4"
18
19
  ],
19
20
  "v6": [
20
21
  "::/128",
21
22
  "::1/128",
22
23
  "::ffff:0:0/96",
23
24
  "::/96",
25
+ "64:ff9b::/96",
26
+ "64:ff9b:1::/48",
24
27
  "100::/64",
28
+ "100:0:0:1::/64",
29
+ "2001:2::/48",
25
30
  "2001:10::/28",
26
31
  "2001:db8::/32",
32
+ "3fff::/20",
33
+ "5f00::/16",
27
34
  "fc00::/7",
28
35
  "fe80::/10",
29
36
  "fec0::/10",
30
37
  "ff00::/8",
31
38
  "2002::/24",
32
39
  "2002:a00::/24",
40
+ "2002:6440::/26",
33
41
  "2002:7f00::/24",
34
42
  "2002:a9fe::/32",
35
43
  "2002:ac10::/28",
36
44
  "2002:c000::/40",
37
45
  "2002:c000:200::/40",
46
+ "2002:c058:6302::/48",
38
47
  "2002:c0a8::/32",
39
48
  "2002:c612::/31",
40
49
  "2002:c633:6400::/40",
41
50
  "2002:cb00:7100::/40",
42
51
  "2002:e000::/20",
43
- "2002:f000::/20",
44
52
  "2002:ffff:ffff::/48",
53
+ "2002:f000::/20",
45
54
  "2001::/40",
46
55
  "2001:0:a00::/40",
56
+ "2001:0:6440::/42",
47
57
  "2001:0:7f00::/40",
48
58
  "2001:0:a9fe::/48",
49
59
  "2001:0:ac10::/44",
50
60
  "2001:0:c000::/56",
51
61
  "2001:0:c000:200::/56",
62
+ "2001:0:c058:6302::/64",
52
63
  "2001:0:c0a8::/48",
53
64
  "2001:0:c612::/47",
54
65
  "2001:0:c633:6400::/56",
55
66
  "2001:0:cb00:7100::/56",
56
67
  "2001:0:e000::/36",
68
+ "2001:0:ffff:ffff::/64",
57
69
  "2001:0:f000::/36",
58
- "2001:0:ffff:ffff::/64"
70
+ "2001:1::/32",
71
+ "2001:2::/31",
72
+ "2001:4::/30",
73
+ "2001:8::/29",
74
+ "2001:20::/27",
75
+ "2001:40::/26",
76
+ "2001:80::/25",
77
+ "2001:100::/24",
78
+ "::/3",
79
+ "4000::/3",
80
+ "6000::/3",
81
+ "8000::/3",
82
+ "a000::/3",
83
+ "c000::/3",
84
+ "e000::/3"
59
85
  ]
60
86
  }
@@ -137,8 +137,18 @@
137
137
  },
138
138
  {
139
139
  "ip": "fe00::",
140
+ "expect": true,
141
+ "why": "past fc00::/7 but inside e000::/3, outside global unicast"
142
+ },
143
+ {
144
+ "ip": "3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff",
145
+ "expect": true,
146
+ "why": "last address inside 3fff::/20; pins the /20 mask width"
147
+ },
148
+ {
149
+ "ip": "3fff:1000::",
140
150
  "expect": false,
141
- "why": "first address past fc00::/7; a mask one bit too wide claims it"
151
+ "why": "first address past 3fff::/20; a mask one bit too wide claims it"
142
152
  },
143
153
  {
144
154
  "ip": "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff",
@@ -177,8 +187,18 @@
177
187
  },
178
188
  {
179
189
  "ip": "100:0:0:1::",
190
+ "expect": true,
191
+ "why": "past 100::/64 but inside 100:0:0:1::/64 and ::/3"
192
+ },
193
+ {
194
+ "ip": "2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff",
195
+ "expect": true,
196
+ "why": "last address inside 2001::/23; pins the /23 mask width"
197
+ },
198
+ {
199
+ "ip": "2001:200::",
180
200
  "expect": false,
181
- "why": "first address past 100::/64; a mask one bit too wide claims it"
201
+ "why": "first address past 2001::/23; a mask one bit too wide claims it"
182
202
  },
183
203
  {
184
204
  "ip": "10.255.255.255",
@@ -231,6 +251,50 @@
231
251
  "why": "first address past 192.0.2.0/24; a mask one bit too wide claims it"
232
252
  }
233
253
  ],
254
+ "ipv4Mapped": [
255
+ {
256
+ "ip": "::ffff:8.8.8.8",
257
+ "carries": "8.8.8.8",
258
+ "expect": false,
259
+ "why": "a public IPv4 visitor, as a server listening on :: sees every one: judged, sent and cached as 8.8.8.8, never as a bogon in ::ffff:0:0/96"
260
+ },
261
+ {
262
+ "ip": "::ffff:10.0.0.1",
263
+ "carries": "10.0.0.1",
264
+ "expect": true,
265
+ "why": "RFC 1918, mapped: a bogon for the same reason 10.0.0.1 is"
266
+ },
267
+ {
268
+ "ip": "::ffff:127.0.0.1",
269
+ "carries": "127.0.0.1",
270
+ "expect": true,
271
+ "why": "loopback, mapped: a local client of a server listening on ::"
272
+ },
273
+ {
274
+ "ip": "::ffff:808:808",
275
+ "carries": "8.8.8.8",
276
+ "expect": false,
277
+ "why": "the same address with its IPv4 half in hex"
278
+ },
279
+ {
280
+ "ip": "0:0:0:0:0:ffff:808:808",
281
+ "carries": "8.8.8.8",
282
+ "expect": false,
283
+ "why": "the same address written in full"
284
+ },
285
+ {
286
+ "ip": "::FFFF:8.8.8.8",
287
+ "carries": "8.8.8.8",
288
+ "expect": false,
289
+ "why": "upper-case hex digits"
290
+ },
291
+ {
292
+ "ip": "::8.8.8.8",
293
+ "carries": "::8.8.8.8",
294
+ "expect": true,
295
+ "why": "IPv4-compatible, not mapped: stays IPv6 and inside ::/96"
296
+ }
297
+ ],
234
298
  "bogonResponse": {
235
299
  "why": "A bogon is answered locally in the full max shape. Every flag is present and false, every detail object is present and empty, and is_bogon marks it as computed rather than served.",
236
300
  "flagsFalse": [
@@ -6601,54 +6665,80 @@
6601
6665
  "172.16.0.0/12",
6602
6666
  "192.0.0.0/24",
6603
6667
  "192.0.2.0/24",
6668
+ "192.88.99.2/32",
6604
6669
  "192.168.0.0/16",
6605
6670
  "198.18.0.0/15",
6606
6671
  "198.51.100.0/24",
6607
6672
  "203.0.113.0/24",
6608
6673
  "224.0.0.0/4",
6609
- "240.0.0.0/4",
6610
- "255.255.255.255/32"
6674
+ "255.255.255.255/32",
6675
+ "240.0.0.0/4"
6611
6676
  ],
6612
6677
  "v6": [
6613
6678
  "::/128",
6614
6679
  "::1/128",
6615
6680
  "::ffff:0:0/96",
6616
6681
  "::/96",
6682
+ "64:ff9b::/96",
6683
+ "64:ff9b:1::/48",
6617
6684
  "100::/64",
6685
+ "100:0:0:1::/64",
6686
+ "2001:2::/48",
6618
6687
  "2001:10::/28",
6619
6688
  "2001:db8::/32",
6689
+ "3fff::/20",
6690
+ "5f00::/16",
6620
6691
  "fc00::/7",
6621
6692
  "fe80::/10",
6622
6693
  "fec0::/10",
6623
6694
  "ff00::/8",
6624
6695
  "2002::/24",
6625
6696
  "2002:a00::/24",
6697
+ "2002:6440::/26",
6626
6698
  "2002:7f00::/24",
6627
6699
  "2002:a9fe::/32",
6628
6700
  "2002:ac10::/28",
6629
6701
  "2002:c000::/40",
6630
6702
  "2002:c000:200::/40",
6703
+ "2002:c058:6302::/48",
6631
6704
  "2002:c0a8::/32",
6632
6705
  "2002:c612::/31",
6633
6706
  "2002:c633:6400::/40",
6634
6707
  "2002:cb00:7100::/40",
6635
6708
  "2002:e000::/20",
6636
- "2002:f000::/20",
6637
6709
  "2002:ffff:ffff::/48",
6710
+ "2002:f000::/20",
6638
6711
  "2001::/40",
6639
6712
  "2001:0:a00::/40",
6713
+ "2001:0:6440::/42",
6640
6714
  "2001:0:7f00::/40",
6641
6715
  "2001:0:a9fe::/48",
6642
6716
  "2001:0:ac10::/44",
6643
6717
  "2001:0:c000::/56",
6644
6718
  "2001:0:c000:200::/56",
6719
+ "2001:0:c058:6302::/64",
6645
6720
  "2001:0:c0a8::/48",
6646
6721
  "2001:0:c612::/47",
6647
6722
  "2001:0:c633:6400::/56",
6648
6723
  "2001:0:cb00:7100::/56",
6649
6724
  "2001:0:e000::/36",
6725
+ "2001:0:ffff:ffff::/64",
6650
6726
  "2001:0:f000::/36",
6651
- "2001:0:ffff:ffff::/64"
6727
+ "2001:1::/32",
6728
+ "2001:2::/31",
6729
+ "2001:4::/30",
6730
+ "2001:8::/29",
6731
+ "2001:20::/27",
6732
+ "2001:40::/26",
6733
+ "2001:80::/25",
6734
+ "2001:100::/24",
6735
+ "::/3",
6736
+ "4000::/3",
6737
+ "6000::/3",
6738
+ "8000::/3",
6739
+ "a000::/3",
6740
+ "c000::/3",
6741
+ "e000::/3"
6652
6742
  ]
6653
6743
  }
6654
6744
  }