python-ipware 2.0.2__py3-none-any.whl → 2.0.4__py3-none-any.whl
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.
- python_ipware/__version__.py +1 -1
- python_ipware/python_ipware.py +19 -18
- {python_ipware-2.0.2.dist-info → python_ipware-2.0.4.dist-info}/METADATA +30 -11
- python_ipware-2.0.4.dist-info/RECORD +9 -0
- {python_ipware-2.0.2.dist-info → python_ipware-2.0.4.dist-info}/WHEEL +1 -1
- python_ipware-2.0.2.dist-info/RECORD +0 -9
- {python_ipware-2.0.2.dist-info → python_ipware-2.0.4.dist-info}/LICENSE +0 -0
- {python_ipware-2.0.2.dist-info → python_ipware-2.0.4.dist-info}/top_level.txt +0 -0
python_ipware/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.0.
|
|
1
|
+
__version__ = "2.0.4"
|
python_ipware/python_ipware.py
CHANGED
|
@@ -28,6 +28,7 @@ class IpWareMeta:
|
|
|
28
28
|
"HTTP_X_CLUSTER_CLIENT_IP", # Rackspace LB and Riverbed Stingray
|
|
29
29
|
"HTTP_FORWARDED_FOR", # RFC 7239
|
|
30
30
|
"HTTP_FORWARDED", # RFC 7239
|
|
31
|
+
"HTTP_CF_CONNECTING_IP", # CloudFlare
|
|
31
32
|
"X-CLIENT-IP", # Microsoft Azure
|
|
32
33
|
"X-REAL-IP", # NGINX
|
|
33
34
|
"X-CLUSTER-CLIENT-IP", # Rackspace Cloud Load Balancers
|
|
@@ -143,12 +144,9 @@ class IpWareProxy:
|
|
|
143
144
|
|
|
144
145
|
def __init__(
|
|
145
146
|
self,
|
|
146
|
-
proxy_count: int =
|
|
147
|
+
proxy_count: Optional[int] = None,
|
|
147
148
|
proxy_list: Optional[List[str]] = None,
|
|
148
149
|
) -> None:
|
|
149
|
-
if proxy_count is None or proxy_count < 0:
|
|
150
|
-
raise ValueError("proxy_count must be a positive integer")
|
|
151
|
-
|
|
152
150
|
self.proxy_count = proxy_count
|
|
153
151
|
self.proxy_list = self._is_valid_proxy_trusted_list(proxy_list or [])
|
|
154
152
|
|
|
@@ -171,15 +169,14 @@ class IpWareProxy:
|
|
|
171
169
|
"""
|
|
172
170
|
Checks if the proxy count is valid
|
|
173
171
|
@param ip_list: list of ip addresses
|
|
174
|
-
@param strict: if True, we must have exactly proxy_count proxies
|
|
172
|
+
@param strict: if True, we must have exactly proxy_count proxies, including `0` proxies
|
|
175
173
|
@return: True if the proxy count is valid, False otherwise
|
|
176
174
|
"""
|
|
177
|
-
|
|
175
|
+
# No proxy count check is required
|
|
176
|
+
if self.proxy_count is None:
|
|
178
177
|
return True
|
|
179
178
|
|
|
180
179
|
ip_count: int = len(ip_list)
|
|
181
|
-
if ip_count < 1:
|
|
182
|
-
return False
|
|
183
180
|
|
|
184
181
|
if strict:
|
|
185
182
|
# our first proxy takes the last ip address and treats it as client ip
|
|
@@ -220,10 +217,6 @@ class IpWareProxy:
|
|
|
220
217
|
if not str(value).startswith(self.proxy_list[index]):
|
|
221
218
|
return False
|
|
222
219
|
|
|
223
|
-
# now all we need is to return the first ip in the list that is not in the trusted proxy list
|
|
224
|
-
# best_client_ip_index = proxy_list_count + 1
|
|
225
|
-
# best_client_ip = ip_list[-best_client_ip_index]
|
|
226
|
-
|
|
227
220
|
return True
|
|
228
221
|
|
|
229
222
|
|
|
@@ -236,11 +229,11 @@ class IpWare(IpWareMeta, IpWareProxy, IpWareIpAddress):
|
|
|
236
229
|
self,
|
|
237
230
|
precedence: Optional[Tuple[str, ...]] = None,
|
|
238
231
|
leftmost: bool = True,
|
|
239
|
-
proxy_count: int =
|
|
232
|
+
proxy_count: Optional[int] = None,
|
|
240
233
|
proxy_list: Optional[List[str]] = None,
|
|
241
234
|
) -> None:
|
|
242
235
|
IpWareMeta.__init__(self, precedence, leftmost)
|
|
243
|
-
IpWareProxy.__init__(self, proxy_count
|
|
236
|
+
IpWareProxy.__init__(self, proxy_count, proxy_list)
|
|
244
237
|
|
|
245
238
|
def get_meta_value(self, meta: Dict[str, str], key: str) -> str:
|
|
246
239
|
"""
|
|
@@ -256,7 +249,13 @@ class IpWare(IpWareMeta, IpWareProxy, IpWareIpAddress):
|
|
|
256
249
|
Given a list of keys, it returns a list of cleaned up values
|
|
257
250
|
@return: a list of values
|
|
258
251
|
"""
|
|
259
|
-
|
|
252
|
+
meta_list: List[str] = []
|
|
253
|
+
for key in self.precedence:
|
|
254
|
+
value = self.get_meta_value(meta, key).strip()
|
|
255
|
+
if value:
|
|
256
|
+
meta_list.append(value)
|
|
257
|
+
|
|
258
|
+
return meta_list
|
|
260
259
|
|
|
261
260
|
def get_client_ip(
|
|
262
261
|
self,
|
|
@@ -271,8 +270,6 @@ class IpWare(IpWareMeta, IpWareProxy, IpWareIpAddress):
|
|
|
271
270
|
private_list: List[OptionalIpAddressType] = []
|
|
272
271
|
|
|
273
272
|
for ip_str in self.get_meta_values(meta):
|
|
274
|
-
if not ip_str:
|
|
275
|
-
continue
|
|
276
273
|
|
|
277
274
|
ip_list = self.get_ips_from_string(ip_str)
|
|
278
275
|
if not ip_list:
|
|
@@ -336,7 +333,11 @@ class IpWare(IpWareMeta, IpWareProxy, IpWareIpAddress):
|
|
|
336
333
|
return best_client_ip, True
|
|
337
334
|
|
|
338
335
|
# the incoming ips match our proxy count
|
|
339
|
-
if
|
|
336
|
+
if (
|
|
337
|
+
self.proxy_count is not None
|
|
338
|
+
and self.proxy_count > 0
|
|
339
|
+
and proxy_count_validated
|
|
340
|
+
):
|
|
340
341
|
best_client_ip_index = self.proxy_count + 1
|
|
341
342
|
best_client_ip = ip_list[-best_client_ip_index]
|
|
342
343
|
return best_client_ip, True
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-ipware
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: A Python package to retrieve user's IP address
|
|
5
5
|
Author-email: Val Neekman <info@neekware.com>
|
|
6
6
|
License: MIT
|
|
@@ -134,6 +134,7 @@ request_headers_precedence_order = (
|
|
|
134
134
|
"HTTP_X_CLUSTER_CLIENT_IP", # Rackspace LB and Riverbed Stingray
|
|
135
135
|
"HTTP_FORWARDED_FOR", # RFC 7239
|
|
136
136
|
"HTTP_FORWARDED", # RFC 7239
|
|
137
|
+
"HTTP_CF_CONNECTING_IP", # CloudFlare
|
|
137
138
|
"X-CLIENT-IP", # Microsoft Azure
|
|
138
139
|
"X-REAL-IP", # NGINX
|
|
139
140
|
"X-CLUSTER-CLIENT-IP", # Rackspace Cloud Load Balancers
|
|
@@ -215,23 +216,41 @@ If your python server is behind a `known` number of proxies, but you deploy on m
|
|
|
215
216
|
You can customize the proxy count by providing your `proxy_count` during initialization when calling `IpWare(proxy_count=2)`.
|
|
216
217
|
|
|
217
218
|
```python
|
|
218
|
-
# In the above scenario, the total number of proxies can be used as a way to filter out unwanted requests.
|
|
219
219
|
from python_ipware import IpWare
|
|
220
220
|
|
|
221
|
-
#
|
|
222
|
-
|
|
221
|
+
# Enforce proxy count
|
|
222
|
+
# proxy_count=0 is valid
|
|
223
|
+
# proxy_count=None to disable proxy_count check
|
|
224
|
+
ipw = IpWare(proxy_count=2)
|
|
223
225
|
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
+
# Example usage in non-strict mode:
|
|
227
|
+
# X-Forwarded-For format: <fake>, <client>, <proxy1>, <proxy2>
|
|
228
|
+
# At least `proxy_count` number of proxies
|
|
229
|
+
ip, trusted_route = ipw.get_client_ip(meta=request.META)
|
|
226
230
|
|
|
231
|
+
# Example usage in strict mode:
|
|
232
|
+
# X-Forwarded-For format: <client>, <proxy1>, <proxy2>
|
|
233
|
+
# Exact `proxy_count` number of proxies
|
|
234
|
+
ip, trusted_route = ipw.get_client_ip(meta=request.META, strict=True)
|
|
235
|
+
```
|
|
227
236
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
ip, trusted_route = ipw.get_client_ip(meta=request.META)
|
|
237
|
+
### Proxy Count & Trusted Proxy List Combo
|
|
238
|
+
In this example, we utilize the total number of proxies as a method to filter out unwanted requests while verifying the trust proxies.
|
|
231
239
|
|
|
240
|
+
```python
|
|
241
|
+
from python_ipware import IpWare
|
|
232
242
|
|
|
233
|
-
#
|
|
234
|
-
|
|
243
|
+
# Enforce both proxy count and trusted proxies
|
|
244
|
+
ipw = IpWare(proxy_count=1, proxy_list=["198.84.193.157"])
|
|
245
|
+
|
|
246
|
+
# Example usage in non-strict mode:
|
|
247
|
+
# X-Forwarded-For format: <fake>, <client>, <proxy1>, <proxy2>
|
|
248
|
+
# At least `proxy_count` number of proxies
|
|
249
|
+
ip, trusted_route = ipw.get_client_ip(meta=request.META)
|
|
250
|
+
|
|
251
|
+
# Example usage in strict mode:
|
|
252
|
+
# X-Forwarded-For format: <client>, <proxy1>
|
|
253
|
+
# Exact `proxy_count` number of proxies
|
|
235
254
|
ip, trusted_route = ipw.get_client_ip(meta=request.META, strict=True)
|
|
236
255
|
```
|
|
237
256
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
python_ipware/__init__.py,sha256=TCZx4mt5Gxr2D_zNU6j0ynopdsAN_v4xeiTWz1OXSpY,87
|
|
2
|
+
python_ipware/__version__.py,sha256=ZOg41aCgKEuObK5WhegikXektFWPJaeZ-TMDh0Ke95M,22
|
|
3
|
+
python_ipware/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
python_ipware/python_ipware.py,sha256=sN3NeWWs96beGzI9x3YZ9ucYnMIZh1Q4fWOOIm2_P-s,11987
|
|
5
|
+
python_ipware-2.0.4.dist-info/LICENSE,sha256=MLpNxpqfTc4TLdcDk3x6k7Vz4lJGBNLV-SxQZlFMDU8,1103
|
|
6
|
+
python_ipware-2.0.4.dist-info/METADATA,sha256=-KqYlSwY52kwnnAMA7ym2A31L1yX8BffjMdZ3I32Wl0,15420
|
|
7
|
+
python_ipware-2.0.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
8
|
+
python_ipware-2.0.4.dist-info/top_level.txt,sha256=URE4dvjpReJtRHyQpJqoBow5EWt_RqVXFn85B9Tq5Xw,14
|
|
9
|
+
python_ipware-2.0.4.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
python_ipware/__init__.py,sha256=TCZx4mt5Gxr2D_zNU6j0ynopdsAN_v4xeiTWz1OXSpY,87
|
|
2
|
-
python_ipware/__version__.py,sha256=tATvJM5shAzfspHYjdVwpV2w3-gDA119NlEYi5X2lFY,22
|
|
3
|
-
python_ipware/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
python_ipware/python_ipware.py,sha256=V6yEmV2kBIrVqWf8eitUO1YFVIL18TdGdh37t2dHf9c,12068
|
|
5
|
-
python_ipware-2.0.2.dist-info/LICENSE,sha256=MLpNxpqfTc4TLdcDk3x6k7Vz4lJGBNLV-SxQZlFMDU8,1103
|
|
6
|
-
python_ipware-2.0.2.dist-info/METADATA,sha256=2H8IHP6sUsA-2I8IqbJDSOPVsBAKFRn-dBUD7ay_TP0,14814
|
|
7
|
-
python_ipware-2.0.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
8
|
-
python_ipware-2.0.2.dist-info/top_level.txt,sha256=URE4dvjpReJtRHyQpJqoBow5EWt_RqVXFn85B9Tq5Xw,14
|
|
9
|
-
python_ipware-2.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|