Codebase list django-ipware / 6a543b2
[ Ondřej Nový ] [ Debian Janitor ] New upstream release. Debian Janitor 2 years ago
15 changed file(s) with 487 addition(s) and 333 deletion(s). Raw diff Collapse all Expand all
0 name: (CI)
1
2 on:
3 push:
4 branches:
5 - ci
6
7 jobs:
8 build:
9 name: Python ${{ matrix.python-version }}, django ${{ matrix.django-version }}
10 runs-on: ubuntu-latest
11 strategy:
12 matrix:
13 python-version: [3.6, 3.7, 3.8, pypy3]
14 django-version: [2.2, 3.0, 3.1, 3.2]
15
16 steps:
17 - uses: actions/checkout@v2
18 - name: setup python
19 uses: actions/setup-python@v2
20 with:
21 python-version: ${{ matrix.python-version }}
22 - name: Install dependencies
23 run: |
24 python -m pip install --upgrade pip
25 pip install -e .
26 pip install coveralls
27 pip install "django~=${{ matrix.django-version }}.0"
28 - name: Run flake8
29 run: |
30 pip install flake8
31 flake8 --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
32 - name: Run pycodestyle
33 run: |
34 pip install pycodestyle
35 pycodestyle --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
36 - name: Run test
37 run: |
38 coverage run --source=ipware manage.py test
39 - name: Coveralls
40 run: coveralls --service=github
41 env:
42 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
0 name: DEV
1
2 # Run on push only for dev/sandbox
3 # Otherwise it may trigger concurrently `push & pull_request` on PRs.
4 on:
5 push:
6 branches:
7 - sandbox
8 - dev
9
10 jobs:
11 build:
12 name: Python ${{ matrix.python-version }}, django ${{ matrix.django-version }}
13 runs-on: ubuntu-latest
14 strategy:
15 matrix:
16 python-version: [3.6, 3.7, 3.8, pypy3]
17 django-version: [2.2, 3.0, 3.1, 3.2]
18
19 steps:
20 - uses: actions/checkout@v2
21 - name: setup python
22 uses: actions/setup-python@v2
23 with:
24 python-version: ${{ matrix.python-version }}
25 - name: Install dependencies
26 run: |
27 python -m pip install --upgrade pip
28 pip install -e .
29 pip install coveralls
30 pip install "django~=${{ matrix.django-version }}.0"
31 - name: Run flake8
32 run: |
33 pip install flake8
34 flake8 --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
35 - name: Run pycodestyle
36 run: |
37 pip install pycodestyle
38 pycodestyle --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
39 - name: Run test
40 run: |
41 coverage run --source=ipware manage.py test
42 - name: Coveralls
43 run: coveralls --service=github
44 env:
45 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
0 name: MAIN
1
2 # Run on push only for main
3 # Otherwise it may trigger concurrently `push & pull_request` on PRs.
4 on:
5 push:
6 branches:
7 - master
8
9
10 jobs:
11 build:
12 name: Python ${{ matrix.python-version }}, django ${{ matrix.django-version }}
13 runs-on: ubuntu-latest
14 strategy:
15 matrix:
16 python-version: [3.6, 3.7, 3.8, pypy3]
17 django-version: [2.2, 3.0, 3.1, 3.2]
18
19 steps:
20 - uses: actions/checkout@v2
21 - name: setup python
22 uses: actions/setup-python@v2
23 with:
24 python-version: ${{ matrix.python-version }}
25 - name: Install dependencies
26 run: |
27 python -m pip install --upgrade pip
28 pip install -e .
29 pip install coveralls
30 pip install "django~=${{ matrix.django-version }}.0"
31 - name: Run flake8
32 run: |
33 pip install flake8
34 flake8 --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
35 - name: Run pycodestyle
36 run: |
37 pip install pycodestyle
38 pycodestyle --exclude=migrations,tests --ignore=E501,E241,E225,E128 .
39 - name: Run test
40 run: |
41 coverage run --source=ipware manage.py test
42 - name: Coveralls
43 run: coveralls --service=github
44 env:
45 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+0
-35
.travis.yml less more
0 sudo: false
1 language: python
2
3 python:
4 - "3.8"
5 - "3.7"
6 - "3.6"
7 - "3.5"
8 - "pypy3"
9
10 env:
11 - DJANGO="django==3.0.7"
12 - DJANGO="django==2.2.8"
13
14 install:
15 - pip install $DJANGO
16 - pip install -e .
17 - pip install pycodestyle
18 - pip install flake8
19 - pip install coveralls
20
21 before_script:
22 - "pycodestyle --exclude=migrations,tests --ignore=E501,E241,E225,E128 ."
23 - "flake8 --exclude=migrations,tests --ignore=E501,E241,E225,E128 ."
24
25 matrix:
26 exclude:
27 - python: "3.5"
28 env: DJANGO="django==3.0.7"
29
30 script: coverage run --source=ipware manage.py test
31
32 after_success:
33 coveralls
34
00 {
1 "python.linting.enabled": false
2 }
1 "python.linting.enabled": false,
2 "cSpell.words": [
3 "Neekman",
4 "Neekware",
5 "Pware",
6 "cmdclass",
7 "getattr",
8 "ipware",
9 "multicast",
10 "noqa",
11 "pycodestyle",
12 "pyflakes",
13 "routable",
14 "setuptools",
15 "stackoverflow",
16 "vneekman"
17 ]
18 }
0 ## 3.0.4 / 3.0.5 / 3.0.6 / 3.0.7
1
2 Enhancement:
3
4 - Clean ups
5
6 ## 3.0.3
7
8 Enhancement:
9
10 - Add support for github action (@awais786)
11
12 ## 3.0.2
13
14 Enhancement:
15
16 - Add support for ppc64le (@kishorkunal-raj)
17
18 ## 3.0.1
19
20 Fix:
21
22 - Ensure no-required build artifacts won't get into the package
23
024 ## 3.0.0
125
226 Enhancement:
3 - Remove deprecated logic
4 - Drop "official" support for py < 3.5
5 - Update to latest Django
6
27
28 - Remove deprecated logic
29 - Drop "official" support for py < 3.5
30 - Update to latest Django
31
732 ## 2.1.1
833
934 Enhancement:
10 - Added deprecation warnings preparing for version 3.0
11 - Update to latest Django
12
35
36 - Added deprecation warnings preparing for version 3.0
37 - Update to latest Django
38
1339 ## 2.1.0
1440
1541 Enhancement:
16 - Added more non-routable ip blocks (@wking)
42
43 - Added more non-routable ip blocks (@wking)
1744
1845 ## 2.0.2
1946
2047 Enhancement:
21 - Added the ability to private the request precedence order on each call
48
49 - Added the ability to private the request precedence order on each call
2250
2351 ## 2.0.1
2452
2553 Enhancement:
26 - Added more private IP blocks to the default list
54
55 - Added more private IP blocks to the default list
2756
2857 ## 2.0.0
2958
3059 Fix:
31 - Update Django versions (@illagrenan)
32 - Update Readme (@sabueso)
33 - Added proxy count
34 - Moved version one readme to /docs
60
61 - Update Django versions (@illagrenan)
62 - Update Readme (@sabueso)
63 - Added proxy count
64 - Moved version one readme to /docs
3565
3666 ## 1.1.6
3767
3868 Fix:
39 - Fix trusted proxies Right2Left + Test & Bumped Django versions (@felixxm)
40 - Changed licensing to MIT
69
70 - Fix trusted proxies Right2Left + Test & Bumped Django versions (@felixxm)
71 - Changed licensing to MIT
4172
4273 ## 1.1.5
4374
4475 Feature:
45 - Added support for trusted proxy configuration
76
77 - Added support for trusted proxy configuration
4678
4779 ## 1.1.4
4880
4981 Enhancement:
5082
51 - Added support for proxies with `underscores_in_headers off;`
52 - Handling hyphen as delimiter - ex: `X-FORWARDED-FOR` instead of `X_FORWARDED_FOR`
53 - Up version Django version in .travis.yml
54
83 - Added support for proxies with `underscores_in_headers off;`
84 - Handling hyphen as delimiter - ex: `X-FORWARDED-FOR` instead of `X_FORWARDED_FOR`
85 - Up version Django version in .travis.yml
5586
5687 ## 1.1.3
5788
5889 Fix:
5990
60 - Fix read me file updating `IPWARE_META_PRECEDENCE_ORDER` reference.
61
91 - Fix read me file updating `IPWARE_META_PRECEDENCE_ORDER` reference.
6292
6393 ## 1.1.2
6494
6595 Updates:
6696
67 - Added support for Django 1.8.6 and Python 3.5.
68 - Dropped support for Django 1.4.x and Python 2.6 and 3.2
69
97 - Added support for Django 1.8.6 and Python 3.5.
98 - Dropped support for Django 1.4.x and Python 2.6 and 3.2
7099
71100 ## 1.1.1
72101
73102 Enhancement:
74103
75 - Added support for X_FORWARDED_FOR
76
104 - Added support for X_FORWARDED_FOR
77105
78106 ## 1.1.0
79107
80108 Enhancement:
81109
82 - Added support for 1.0.0.0/8 and 2.0.0.0/8 blocks
83
110 - Added support for 1.0.0.0/8 and 2.0.0.0/8 blocks
84111
85112 ## 1.0.0
86113
87114 Enhancement:
88115
89 - Promoting to production grade
90
116 - Promoting to production grade
91117
92118 ## 0.1.1
93119
94120 Enhancement:
95121
96 - Support for Left2Right or Right2Left Proxy IP Lookup
97
122 - Support for Left2Right or Right2Left Proxy IP Lookup
98123
99124 ## 0.1.0
100125
101126 Enhancement:
102127
103 - pypy support
104 - PY3.4 support
105
128 - pypy support
129 - PY3.4 support
106130
107131 ## 0.0.9
108132
109133 Enhancement:
110134
111 - Django 1.7 official support
112 - First non-loopback private IP match is best matched now.
113
135 - Django 1.7 official support
136 - First non-loopback private IP match is best matched now.
114137
115138 ## 0.0.8
116139
117140 Enhancement:
118141
119 - Django 1.7 support
120 - PEP8 Compliance
121 - Bump Alpha to Beta
122
142 - Django 1.7 support
143 - PEP8 Compliance
144 - Bump Alpha to Beta
123145
124146 ## 0.0.6
125147
126148 Enhancement:
127149
128 - Converted print statements to new format. (Python 3.x)
129 - Replaced deprecated unit test APIs
130
150 - Converted print statements to new format. (Python 3.x)
151 - Replaced deprecated unit test APIs
131152
132153 ## 0.0.5
133154
134155 Enhancement:
135156
136 - Added Python 3.2 and 3.3 support
137
157 - Added Python 3.2 and 3.3 support
138158
139159 ## 0.0.4
140160
141161 Enhancement:
142162
143 - Added changelog file
144 - Added more private ip prefixes
145
163 - Added changelog file
164 - Added more private ip prefixes
146165
147166 ## 0.0.3
148167
149168 Features:
150169
151 - Added get_ip() to return the best-matched IP
152 - Removed get_ip_address_from_request()
170 - Added get_ip() to return the best-matched IP
171 - Removed get_ip_address_from_request()
153172
154173 Bugfixes:
155174
156 - Expended the private IP range
157
175 - Expended the private IP range
158176
159177 ## 0.0.2
160178
161179 Features:
162180
163 - IPv6 support
164 - Added get_real_ip(), the shorter version of get_ip_address_from_request()
165
181 - IPv6 support
182 - Added get_real_ip(), the shorter version of get_ip_address_from_request()
166183
167184 ## 0.0.1
168185
169186 Features:
170187
171 - Initial Release
188 - Initial Release
0 Django IPware
1 ====================
0 # Django IPware
21
32 **A Django application to retrieve client's IP address**
43
65 [![version-image]][version-link]
76 [![coverage-image]][coverage-link]
87
9 Overview
10 ====================
8 # Overview
119
1210 **Best attempt** to get client's IP address while keeping it **DRY**.
1311
14 Notice
15 ====================
16
17 There is not a good *out-of-the-box* solution against fake IP addresses, aka *IP Address Spoofing*.
12 # Notice
13
14 There is not a good _out-of-the-box_ solution against fake IP addresses, aka _IP Address Spoofing_.
1815 You are encouraged to read the ([Advanced users](README.md#advanced-users)) section of this page and
19 use `trusted_proxies_ips` and/or `proxy_count` features to match your needs, especially *if* you are
20 planning to include `ipware` in any authentication, security or *anti-fraud* related architecture.
21
22
23 How to install
24 ====================
16 use `trusted_proxies_ips` and/or `proxy_count` features to match your needs, especially _if_ you are
17 planning to include `ipware` in any authentication, security or _anti-fraud_ related architecture.
18
19 # How to install
2520
2621 1. easy_install django-ipware
2722 2. pip install django-ipware
3328 b. cd into django-ipware-* directory
3429 c. run python setup.py install
3530
36
37 How to use
38 ====================
39
40 ```python
41 # In a view or a middleware where the `request` object is available
42
43 from ipware import get_client_ip
44 client_ip, is_routable = get_client_ip(request)
45 if client_ip is None:
46 # Unable to get the client's IP address
47 else:
48 # We got the client's IP address
49 if is_routable:
50 # The client's IP address is publicly routable on the Internet
51 else:
52 # The client's IP address is private
53
54 # Order of precedence is (Public, Private, Loopback, None)
55 ```
56
57
58 Advanced users:
59 ====================
31 # How to use
32
33 ```python
34 # In a view or a middleware where the `request` object is available
35
36 from ipware import get_client_ip
37 client_ip, is_routable = get_client_ip(request)
38 if client_ip is None:
39 # Unable to get the client's IP address
40 else:
41 # We got the client's IP address
42 if is_routable:
43 # The client's IP address is publicly routable on the Internet
44 else:
45 # The client's IP address is private
46
47 # Order of precedence is (Public, Private, Loopback, None)
48 ```
49
50 # Advanced users:
6051
6152 - ### Precedence Order
62 The default meta precedence order is top to bottom. However, you may customize the order
63 by providing your own `IPWARE_META_PRECEDENCE_ORDER` by adding it to your project's settings.py
64
65 ```python
66 # The default meta precedence order
67 IPWARE_META_PRECEDENCE_ORDER = (
68 'HTTP_X_FORWARDED_FOR', 'X_FORWARDED_FOR', # <client>, <proxy1>, <proxy2>
69 'HTTP_CLIENT_IP',
70 'HTTP_X_REAL_IP',
71 'HTTP_X_FORWARDED',
72 'HTTP_X_CLUSTER_CLIENT_IP',
73 'HTTP_FORWARDED_FOR',
74 'HTTP_FORWARDED',
75 'HTTP_VIA',
76 'REMOTE_ADDR',
77 )
78 ```
79 **Alternatively**, you can provide your custom *request header meta precedence order* when calling `get_client_ip()`.
53
54 The default meta precedence order is top to bottom. However, you may customize the order
55 by providing your own `IPWARE_META_PRECEDENCE_ORDER` by adding it to your project's settings.py
56
57 ```python
58 # The default meta precedence order
59 IPWARE_META_PRECEDENCE_ORDER = (
60 'HTTP_X_FORWARDED_FOR', 'X_FORWARDED_FOR', # <client>, <proxy1>, <proxy2>
61 'HTTP_CLIENT_IP',
62 'HTTP_X_REAL_IP',
63 'HTTP_X_FORWARDED',
64 'HTTP_X_CLUSTER_CLIENT_IP',
65 'HTTP_FORWARDED_FOR',
66 'HTTP_FORWARDED',
67 'HTTP_VIA',
68 'REMOTE_ADDR',
69 )
70 ```
71
72 **Alternatively**, you can provide your custom _request header meta precedence order_ when calling `get_client_ip()`.
73
8074 ```python
8175 get_client_ip(request, request_header_order=['X_FORWARDED_FOR'])
8276 get_client_ip(request, request_header_order=['X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR'])
8579 ### Private Prefixes
8680
8781 You may customize the prefixes to indicate an IP address is private. This is done by adding your
88 own `IPWARE_PRIVATE_IP_PREFIX` to your project's settings.py. IP addresses matching the following
89 prefixes are considered *private* & are **not** publicly routable.
90
91 ```python
92 # The default private IP prefixes
93 IPWARE_PRIVATE_IP_PREFIX = getattr(settings,
94 'IPWARE_PRIVATE_IP_PREFIX', (
95 '0.', # messages to software
96 '10.', # class A private block
97 '100.64.', '100.65.', '100.66.', '100.67.', '100.68.', '100.69.',
98 '100.70.', '100.71.', '100.72.', '100.73.', '100.74.', '100.75.',
99 '100.76.', '100.77.', '100.78.', '100.79.', '100.80.', '100.81.',
100 '100.82.', '100.83.', '100.84.', '100.85.', '100.86.', '100.87.',
101 '100.88.', '100.89.', '100.90.', '100.91.', '100.92.', '100.93.',
102 '100.94.', '100.95.', '100.96.', '100.97.', '100.98.', '100.99.',
103 '100.100.', '100.101.', '100.102.', '100.103.', '100.104.', '100.105.',
104 '100.106.', '100.107.', '100.108.', '100.109.', '100.110.', '100.111.',
105 '100.112.', '100.113.', '100.114.', '100.115.', '100.116.', '100.117.',
106 '100.118.', '100.119.', '100.120.', '100.121.', '100.122.', '100.123.',
107 '100.124.', '100.125.', '100.126.', '100.127.', # carrier-grade NAT
108 '169.254.', # link-local block
109 '172.16.', '172.17.', '172.18.', '172.19.',
110 '172.20.', '172.21.', '172.22.', '172.23.',
111 '172.24.', '172.25.', '172.26.', '172.27.',
112 '172.28.', '172.29.', '172.30.', '172.31.', # class B private blocks
113 '192.0.0.', # reserved for IANA special purpose address registry
114 '192.0.2.', # reserved for documentation and example code
115 '192.168.', # class C private block
116 '198.18.', '198.19.', # reserved for inter-network communications between two separate subnets
117 '198.51.100.', # reserved for documentation and example code
118 '203.0.113.', # reserved for documentation and example code
119 '224.', '225.', '226.', '227.', '228.', '229.', '230.', '231.', '232.',
120 '233.', '234.', '235.', '236.', '237.', '238.', '239.', # multicast
121 '240.', '241.', '242.', '243.', '244.', '245.', '246.', '247.', '248.',
122 '249.', '250.', '251.', '252.', '253.', '254.', '255.', # reserved
123 ) + (
124 '::', # Unspecified address
125 '::ffff:', '2001:10:', '2001:20:' # messages to software
126 '2001::', # TEREDO
127 '2001:2::', # benchmarking
128 '2001:db8:', # reserved for documentation and example code
129 'fc00:', # IPv6 private block
130 'fe80:', # link-local unicast
131 'ff00:', # IPv6 multicast
132 )
133 )
134 ```
82 own `IPWARE_PRIVATE_IP_PREFIX` to your project's settings.py. IP addresses matching the following
83 prefixes are considered _private_ & are **not** publicly routable.
84
85 ```python
86 # The default private IP prefixes
87 IPWARE_PRIVATE_IP_PREFIX = getattr(settings,
88 'IPWARE_PRIVATE_IP_PREFIX', (
89 '0.', # messages to software
90 '10.', # class A private block
91 '100.64.', '100.65.', '100.66.', '100.67.', '100.68.', '100.69.',
92 '100.70.', '100.71.', '100.72.', '100.73.', '100.74.', '100.75.',
93 '100.76.', '100.77.', '100.78.', '100.79.', '100.80.', '100.81.',
94 '100.82.', '100.83.', '100.84.', '100.85.', '100.86.', '100.87.',
95 '100.88.', '100.89.', '100.90.', '100.91.', '100.92.', '100.93.',
96 '100.94.', '100.95.', '100.96.', '100.97.', '100.98.', '100.99.',
97 '100.100.', '100.101.', '100.102.', '100.103.', '100.104.', '100.105.',
98 '100.106.', '100.107.', '100.108.', '100.109.', '100.110.', '100.111.',
99 '100.112.', '100.113.', '100.114.', '100.115.', '100.116.', '100.117.',
100 '100.118.', '100.119.', '100.120.', '100.121.', '100.122.', '100.123.',
101 '100.124.', '100.125.', '100.126.', '100.127.', # carrier-grade NAT
102 '169.254.', # link-local block
103 '172.16.', '172.17.', '172.18.', '172.19.',
104 '172.20.', '172.21.', '172.22.', '172.23.',
105 '172.24.', '172.25.', '172.26.', '172.27.',
106 '172.28.', '172.29.', '172.30.', '172.31.', # class B private blocks
107 '192.0.0.', # reserved for IANA special purpose address registry
108 '192.0.2.', # reserved for documentation and example code
109 '192.168.', # class C private block
110 '198.18.', '198.19.', # reserved for inter-network communications between two separate subnets
111 '198.51.100.', # reserved for documentation and example code
112 '203.0.113.', # reserved for documentation and example code
113 '224.', '225.', '226.', '227.', '228.', '229.', '230.', '231.', '232.',
114 '233.', '234.', '235.', '236.', '237.', '238.', '239.', # multicast
115 '240.', '241.', '242.', '243.', '244.', '245.', '246.', '247.', '248.',
116 '249.', '250.', '251.', '252.', '253.', '254.', '255.', # reserved
117 ) + (
118 '::', # Unspecified address
119 '::ffff:', '2001:10:', '2001:20:' # messages to software
120 '2001::', # TEREDO
121 '2001:2::', # benchmarking
122 '2001:db8:', # reserved for documentation and example code
123 'fc00:', # IPv6 private block
124 'fe80:', # link-local unicast
125 'ff00:', # IPv6 multicast
126 )
127 )
128 ```
135129
136130 ### Trusted Proxies
137131
139133 by providing the `trusted` proxy list when calling `get_client_ip(request, proxy_trusted_ips=['177.139.233.133'])`.
140134 In the following example, your load balancer (LB) can be seen as a `trusted` proxy.
141135
142 ```
143 `Real` Client <public> <---> <public> LB (Server) <private> <--------> <private> Django Server
144 ^
145 |
146 `Fake` Client <private> <---> <private> LB (Server) <private> ---^
147 ```
148
149
150 ```python
151 # In the above scenario, use your load balancer's IP address as a way to filter out unwanted requests.
152 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.133'])
153
154 # If you have multiple proxies, simply add them to the list
155 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.133', '177.139.233.134'])
156
157 # For proxy servers with fixed sub-domain and dynamic IP, use the following pattern.
158 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.', '177.140'])
159 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.', '177.139.240'])
160 ```
136 ```
137 `Real` Client <public> <---> <public> LB (Server) <private> <--------> <private> Django Server
138 ^
139 |
140 `Fake` Client <private> <---> <private> LB (Server) <private> ---^
141 ```
142
143 ```python
144 # In the above scenario, use your load balancer IP address as a way to filter out unwanted requests.
145 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.133'])
146
147 # If you have multiple proxies, simply add them to the list
148 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.133', '177.139.233.134'])
149
150 # For proxy servers with fixed sub-domain and dynamic IP, use the following pattern.
151 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.', '177.140'])
152 client_ip, is_routable = get_client_ip(request, proxy_trusted_ips=['177.139.233.', '177.139.240'])
153 ```
161154
162155 ### Proxy Count
163156
164 If your Django server is behind a *known* number of proxy server(s), you can filter out unwanted requests
165 by providing the *number* of proxies when calling `get_client_ip(request, proxy_count=1)`.
166 In the following example, your load balancer (LB) can be seen as the *only* proxy.
167
168 ```
169 `Real` Client <public> <---> <public> LB (Server) <private> <--------> <private> Django Server
170 ^
171 |
172 `Fake` Client <private> ---^
173 ```
174
175 ```python
176 # In the above scenario, the total number of proxies can be used as a way to filter out unwanted requests.
177 client_ip, is_routable = get_client_ip(request, proxy_count=1)
178
179 # The above may be very useful in cases where your proxy server's IP address is assigned dynamically.
180 # However, If you have the proxy IP address, you can use it in combination to the proxy count.
181 client_ip, is_routable = get_client_ip(request, proxy_count=1, proxy_trusted_ips=['177.139.233.133'])
182 ```
157 If your Django server is behind a _known_ number of proxy server(s), you can filter out unwanted requests
158 by providing the _number_ of proxies when calling `get_client_ip(request, proxy_count=1)`.
159 In the following example, your load balancer (LB) can be seen as the _only_ proxy.
160
161 ```
162 `Real` Client <public> <---> <public> LB (Server) <private> <--------> <private> Django Server
163 ^
164 |
165 `Fake` Client <private> ---^
166 ```
167
168 ```python
169 # In the above scenario, the total number of proxies can be used as a way to filter out unwanted requests.
170 client_ip, is_routable = get_client_ip(request, proxy_count=1)
171
172 # The above may be very useful in cases where your proxy server's IP address is assigned dynamically.
173 # However, If you have the proxy IP address, you can use it in combination to the proxy count.
174 client_ip, is_routable = get_client_ip(request, proxy_count=1, proxy_trusted_ips=['177.139.233.133'])
175 ```
183176
184177 ### Originating Request
185178
186179 If your proxy server is configured such that the right-most IP address is that of the originating client, you
187180 can indicate `right-most` as your `proxy_order` when calling `get_client_ip(request, proxy_order="right-most")`.
188181 Please note that the [de-facto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) standard
189 for the originating client IP address is the `left-most` as per `<client>, <proxy1>, <proxy2>`.
190
191 Running the tests
192 ====================
182 for the originating client IP address is the `left-most` as per `<client>, <proxy1>, <proxy2>`.
183
184 # Running the tests
193185
194186 To run the tests against the current environment:
195187
196188 python manage.py test
197189
198
199 License
200 ====================
190 # License
201191
202192 Released under a ([MIT](LICENSE)) license.
203193
204
205 Version
206 ====================
194 # Version
195
207196 X.Y.Z Version
208197
209198 `MAJOR` version -- when you make incompatible API changes,
212201
213202 [status-image]: https://travis-ci.org/un33k/django-ipware.svg?branch=master
214203 [status-link]: https://travis-ci.org/un33k/django-ipware
215
216204 [version-image]: https://img.shields.io/pypi/v/django-ipware.svg
217205 [version-link]: https://pypi.python.org/pypi/django-ipware
218
219206 [coverage-image]: https://coveralls.io/repos/un33k/django-ipware/badge.svg
220207 [coverage-link]: https://coveralls.io/r/un33k/django-ipware
221
222208 [download-image]: https://img.shields.io/pypi/dm/django-ipware.svg
223209 [download-link]: https://pypi.python.org/pypi/django-ipware
224210
225
226 Sponsors
227 ====================
211 # Sponsors
228212
229213 [Neekware Inc.](http://neekware.com)
0 django-ipware (3.0.0-2) UNRELEASED; urgency=medium
0 django-ipware (3.0.7-1) UNRELEASED; urgency=medium
11
2 [ Ondřej Nový ]
23 * d/control: Update Maintainer field with new Debian Python Team
34 contact address.
45 * d/control: Update Vcs-* fields with new Debian Python Team Salsa
56 layout.
67
7 -- Ondřej Nový <onovy@debian.org> Thu, 24 Sep 2020 08:49:21 +0200
8 [ Debian Janitor ]
9 * New upstream release.
10
11 -- Ondřej Nový <onovy@debian.org> Thu, 19 Aug 2021 10:09:41 -0000
812
913 django-ipware (3.0.0-1) unstable; urgency=low
1014
0 ### Nginx Users
1
2 By default,using Ningx as a reverse proxy to Gunicorn doesn't forward the client's IP to gunicorn.
3 As a reverse proxy, NGINX will receive HTTP requests from clients and then send those requests to our
4 Gunicorn WSGI server. The problem is that NGINX hides information from our WSGI server.
5 The HTTP request that Gunicorn receives is not the same as the one that NGINX received from the client.
6 To solve this problem, open up your `nginx conf file` and add the following lines to the `location` block
7 ```
8 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 proxy_set_header Host $host;
10 proxy_set_header X-Forwarded-Proto $scheme;
11 ```
12
13 ```
14 server {
15 listen 80;
16 location / {
17 include proxy_params;
18 proxy_pass http://unix:/<where_your_sock_file_is>/coincard.sock;
19 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
20 proxy_set_header Host $host;
21 proxy_set_header X-Forwarded-Proto $scheme;
22 }
23 }
24
25 ```
00 from .ip import get_client_ip # noqa
11
22 default_app_config = 'ipware.apps.IPwareConfig'
3
4 __author__ = 'Val Neekman @ Neekware Inc. [@vneekman]'
5 __description__ = "A Django application to retrieve user's IP address"
6 __version__ = '3.0.0'
0 __title__ = 'django-ipware'
1 __author__ = 'Val Neekman'
2 __author_email__ = 'info@neekware.com'
3 __description__ = "A Django application to retrieve user's IP address"
4 __url__ = 'https://github.com/un33k/django-ipware'
5 __license__ = 'MIT'
6 __copyright__ = 'Copyright 2020 Val Neekman @ Neekware Inc.'
7 __version__ = '3.0.7'
0 [build-system]
1 requires = [
2 "setuptools>=42",
3 "wheel"
4 ]
5 build-backend = "setuptools.build_meta"
0 Django==3.0.7
1 pycodestyle==2.6.0
2 flake8==3.8.3
0 Django==3.2.5
1 pycodestyle==2.7.0
2 flake8==3.9.2
3 twine==3.4.2
11 universal = 1
22
33 [metadata]
4 license_file = LICENSE
4 license_file = LICENSE
00 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
2
3 from setuptools import setup
4 import re
1 # Learn more: https://github.com/kennethreitz/setup.py
52 import os
63 import sys
74
8
9 name = 'django-ipware'
10 package = 'ipware'
11 description = "A Django utility application that returns client's real IP address"
12 url = 'https://github.com/un33k/django-ipware'
13 author = 'Val Neekman'
14 author_email = 'info@neekware.com'
15 license = 'MIT'
16 install_requires = ['']
17 classifiers = [
18 'Development Status :: 5 - Production/Stable',
19 'Environment :: Web Environment',
20 'Intended Audience :: Developers',
21 'License :: OSI Approved :: MIT License',
22 'Operating System :: OS Independent',
23 'Programming Language :: Python',
24 'Programming Language :: Python :: 2.7',
25 'Programming Language :: Python :: 3.4',
26 'Programming Language :: Python :: 3.5',
27 'Programming Language :: Python :: 3.6',
28 'Topic :: Utilities'
29 ]
5 from codecs import open
6 from shutil import rmtree
7 from setuptools import setup
308
319
32 def get_version(package):
33 """
34 Return package version as listed in `__version__` in `init.py`.
35 """
36 init_py = open(os.path.join(package, '__init__.py')).read()
37 return re.search("^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
10 package = 'ipware'
11 python_requires = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
12 here = os.path.abspath(os.path.dirname(__file__))
13
14 requires = []
15 test_requirements = []
16
17 about = {}
18 with open(os.path.join(here, package, '__version__.py'), 'r', 'utf-8') as f:
19 exec(f.read(), about)
20
21 with open('README.md', 'r', 'utf-8') as f:
22 readme = f.read()
3823
3924
40 def get_packages(package):
41 """
42 Return root package and all sub-packages.
43 """
44 return [dirpath
45 for dirpath, dirnames, filenames in os.walk(package)
46 if os.path.exists(os.path.join(dirpath, '__init__.py'))]
25 def status(s):
26 print('\033[1m{0}\033[0m'.format(s))
4727
4828
49 def get_package_data(package):
50 """
51 Return all files under the root package, that are not in a
52 package themselves.
53 """
54 walk = [(dirpath.replace(package + os.sep, '', 1), filenames)
55 for dirpath, dirnames, filenames in os.walk(package)
56 if not os.path.exists(os.path.join(dirpath, '__init__.py'))]
29 # 'setup.py publish' shortcut.
30 if sys.argv[-1] == 'publish':
31 try:
32 status('Removing previous builds…')
33 rmtree(os.path.join(here, 'dist'))
34 except OSError:
35 pass
5736
58 filepaths = []
59 for base, filenames in walk:
60 filepaths.extend([os.path.join(base, filename)
61 for filename in filenames])
62 return {package: filepaths}
37 status('Building Source and Wheel (universal) distribution…')
38 os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable))
6339
40 status('Uploading the package to PyPI via Twine…')
41 os.system('twine upload dist/*')
6442
65 if sys.argv[-1] == 'publish':
66 os.system("python setup.py sdist upload")
67 args = {'version': get_version(package)}
68 print("You probably want to also tag the version now:")
69 print(" git tag -a %(version)s -m 'version %(version)s' && git push --tags" % args)
43 status('Pushing git tags…')
44 os.system('git tag v{0}'.format(about['__version__']))
45 os.system('git push --tags')
7046 sys.exit()
7147
72
7348 setup(
74 name=name,
75 version=get_version(package),
76 url=url,
77 license=license,
78 description=description,
79 author=author,
80 author_email=author_email,
81 packages=get_packages(package),
82 package_data=get_package_data(package),
83 install_requires=install_requires,
84 classifiers=classifiers
49 name=about['__title__'],
50 version=about['__version__'],
51 description=about['__description__'],
52 long_description=readme,
53 long_description_content_type='text/markdown',
54 author=about['__author__'],
55 author_email=about['__author_email__'],
56 url=about['__url__'],
57 packages=[package],
58 package_data={'': ['LICENSE']},
59 package_dir={'ipware': 'ipware'},
60 include_package_data=True,
61 python_requires=python_requires,
62 install_requires=requires,
63 license=about['__license__'],
64 zip_safe=False,
65 classifiers=[
66 'Development Status :: 5 - Production/Stable',
67 'Intended Audience :: Developers',
68 'Natural Language :: English',
69 'License :: OSI Approved :: Apache Software License',
70 'Programming Language :: Python',
71 'Programming Language :: Python :: 3',
72 'Programming Language :: Python :: 3.6',
73 'Programming Language :: Python :: 3.7',
74 'Programming Language :: Python :: 3.8',
75 'Programming Language :: Python :: 3.9',
76 ],
77 cmdclass={},
78 tests_require=test_requirements,
79 extras_require={},
80 project_urls={},
8581 )