d0rk3r 1.0.0__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.
- d0rk3r-1.0.0/LICENSE +21 -0
- d0rk3r-1.0.0/MANIFEST.in +4 -0
- d0rk3r-1.0.0/PKG-INFO +258 -0
- d0rk3r-1.0.0/README.md +222 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/PKG-INFO +258 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/SOURCES.txt +14 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/dependency_links.txt +1 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/entry_points.txt +2 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/requires.txt +7 -0
- d0rk3r-1.0.0/d0rk3r.egg-info/top_level.txt +1 -0
- d0rk3r-1.0.0/d0rk3r_pkg/__init__.py +13 -0
- d0rk3r-1.0.0/d0rk3r_pkg/cli.py +311 -0
- d0rk3r-1.0.0/d0rk3r_pkg/proxy_fetcher.py +153 -0
- d0rk3r-1.0.0/pyproject.toml +57 -0
- d0rk3r-1.0.0/requirements.txt +2 -0
- d0rk3r-1.0.0/setup.cfg +4 -0
d0rk3r-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hlaing Bwar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
d0rk3r-1.0.0/MANIFEST.in
ADDED
d0rk3r-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: d0rk3r
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Shodan IP scraper with auto-proxy rotation. No API key needed.
|
|
5
|
+
Author-email: Hlaing Bwar <infohlaingbwar@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/infohlaingbwar/d0rk3r
|
|
8
|
+
Project-URL: Documentation, https://www.hlaingbwar.com/articles/d0rk3r-shodan-ip-scraper-bug-bounty
|
|
9
|
+
Project-URL: Repository, https://github.com/infohlaingbwar/d0rk3r
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/infohlaingbwar/d0rk3r/issues
|
|
11
|
+
Keywords: shodan,osint,recon,bug-bounty,pentesting,proxy,scraper,security
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Requires-Python: >=3.7
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: requests[socks]>=2.25.0
|
|
30
|
+
Requires-Dist: beautifulsoup4>=4.9.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
33
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
34
|
+
Requires-Dist: flake8>=4.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# D0RK3R
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
|
|
41
|
+
<img src="logo.png" alt="D0RK3R Logo" width="600"/>
|
|
42
|
+
|
|
43
|
+
**🔍 Shodan IP scraper with auto-proxy rotation. No API key needed.**
|
|
44
|
+
|
|
45
|
+
[](https://www.python.org/downloads/)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://github.com/infohlaingbwar/d0rk3r/stargazers)
|
|
48
|
+
[](https://github.com/infohlaingbwar/d0rk3r/issues)
|
|
49
|
+
[](CONTRIBUTING.md)
|
|
50
|
+
|
|
51
|
+
Perfect for OSINT, bug bounty & pentesting.
|
|
52
|
+
|
|
53
|
+
[Features](#features) • [Install](#install) • [Usage](#usage) • [Examples](#shodan-dork-syntax)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
✅ **Auto-proxy** — Fetch working proxies from GitHub automatically
|
|
61
|
+
✅ **Proxy rotation** — Bypass Shodan rate limits
|
|
62
|
+
✅ **Smart caching** — Reuse proxies for 6 hours
|
|
63
|
+
✅ **No API key** — Scrapes public Shodan search
|
|
64
|
+
✅ **Fast extraction** — Get 100s-1000s of IPs in seconds
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
72
|
+
cd d0rk3r
|
|
73
|
+
pip install requests[socks]
|
|
74
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Auto-installs `requests` if missing.
|
|
78
|
+
|
|
79
|
+
### Termux
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pkg install python
|
|
83
|
+
pip install requests[socks]
|
|
84
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
85
|
+
cd d0rk3r
|
|
86
|
+
python d0rk3r.py -q "port:443" --auto-proxy
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Kali / Debian / Ubuntu / WSL (PEP 668 error)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip3 install --break-system-packages requests[socks]
|
|
93
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
### Auto-proxy (recommended)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# CVE hunting
|
|
104
|
+
python3 d0rk3r.py -q "Apache/2.4.49" --auto-proxy -o results.txt
|
|
105
|
+
|
|
106
|
+
# Bug bounty recon
|
|
107
|
+
python3 d0rk3r.py -q 'org:"Tesla Motors"' --auto-proxy --pages 3
|
|
108
|
+
|
|
109
|
+
# IoT devices
|
|
110
|
+
python3 d0rk3r.py -q "port:554 rtsp country:MM" --auto-proxy
|
|
111
|
+
|
|
112
|
+
# Vulnerable hosts
|
|
113
|
+
python3 d0rk3r.py -q "vuln:CVE-2021-41773" --auto-proxy
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Manual proxy file
|
|
117
|
+
|
|
118
|
+
Create `proxy.txt`:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
http://user:pass@1.2.3.4:8080
|
|
122
|
+
socks5://5.6.7.8:1080
|
|
123
|
+
http://9.10.11.12:3128
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python3 d0rk3r.py -q "port:443" -p proxy.txt --pages 5
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### No proxy (direct)
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
python3 d0rk3r.py -q "nginx country:MM"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Shodan Dork Syntax
|
|
141
|
+
|
|
142
|
+
| Syntax | Example | Description |
|
|
143
|
+
|--------|---------|-------------|
|
|
144
|
+
| `port:` | `port:22` | SSH open hosts |
|
|
145
|
+
| `country:` | `country:MM` | Myanmar servers |
|
|
146
|
+
| `city:` | `city:Yangon` | City location |
|
|
147
|
+
| `org:` | `org:"MPT"` | Organization |
|
|
148
|
+
| `hostname:` | `hostname:gov.mm` | Domain names |
|
|
149
|
+
| `os:` | `os:Windows` | Operating system |
|
|
150
|
+
| `product:` | `product:nginx` | Software |
|
|
151
|
+
| `vuln:` | `vuln:CVE-2021-41773` | CVE vulnerable |
|
|
152
|
+
| `http.title:` | `http.title:"admin"` | Page titles |
|
|
153
|
+
| `ssl:` | `ssl:"Myanmar"` | SSL cert info |
|
|
154
|
+
|
|
155
|
+
**Combine queries:**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python3 d0rk3r.py -q "Apache/2.4.49 country:MM port:443" --auto-proxy
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Flags
|
|
164
|
+
|
|
165
|
+
| Flag | Description |
|
|
166
|
+
|------|-------------|
|
|
167
|
+
| `-q` | Shodan dork query (required) |
|
|
168
|
+
| `--auto-proxy` | Auto-fetch proxies from GitHub |
|
|
169
|
+
| `-p` | Path to manual proxy file |
|
|
170
|
+
| `--pages` | Requests per proxy (default: 2) |
|
|
171
|
+
| `--page-max` | Max total requests (0 = auto) |
|
|
172
|
+
| `-o` | Save output to file |
|
|
173
|
+
| `--timeout` | Request timeout in sec (default: 10) |
|
|
174
|
+
| `--delay` | Delay between requests in sec (default: 0.5) |
|
|
175
|
+
| `--no-banner` | Skip banner |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## How It Works
|
|
180
|
+
|
|
181
|
+
### Auto-Proxy
|
|
182
|
+
|
|
183
|
+
1. Fetches fresh proxies from GitHub public lists
|
|
184
|
+
2. Verifies working proxies (tests sample of 100)
|
|
185
|
+
3. Caches proxies for 6 hours
|
|
186
|
+
4. Rotates proxies during scraping
|
|
187
|
+
|
|
188
|
+
### Shodan Bypass
|
|
189
|
+
|
|
190
|
+
Shodan free gives ~2 pages per IP.
|
|
191
|
+
|
|
192
|
+
With proxy rotation:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
Proxy A → page 1 (~300 IPs)
|
|
196
|
+
Proxy B → page 1 (~300 new IPs)
|
|
197
|
+
Proxy C → page 1 (~300 new IPs)
|
|
198
|
+
...
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
10 proxies × 2 pages = 600-3000+ unique IPs.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Example Output
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
$ python3 d0rk3r.py -q "nginx" --auto-proxy --pages 1
|
|
209
|
+
|
|
210
|
+
[*] Auto-fetching proxies...
|
|
211
|
+
[+] Loaded 13 working proxies
|
|
212
|
+
┌─ Proxies : 13
|
|
213
|
+
├─ Requests : 13 (1 per proxy)
|
|
214
|
+
└─ Query : nginx
|
|
215
|
+
|
|
216
|
+
════════════════════════════════════════════════
|
|
217
|
+
✔ 1005 unique IPs │ 1 req OK │ 12 fail │ 55.0s
|
|
218
|
+
════════════════════════════════════════════════
|
|
219
|
+
├─ 101.230.14.203
|
|
220
|
+
├─ 102.182.100.18
|
|
221
|
+
├─ 103.100.84.76
|
|
222
|
+
...
|
|
223
|
+
└─ 1005 total
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Files
|
|
229
|
+
|
|
230
|
+
| File | Purpose |
|
|
231
|
+
|------|---------|
|
|
232
|
+
| `d0rk3r.py` | Main script |
|
|
233
|
+
| `proxy_fetcher.py` | Auto-proxy module |
|
|
234
|
+
| `.proxy_cache.txt` | Cached proxies (auto-generated) |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Note
|
|
239
|
+
|
|
240
|
+
This scrapes Shodan's public web search. IP accuracy is not guaranteed. Always verify results yourself.
|
|
241
|
+
|
|
242
|
+
For educational and authorized testing only.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Contributors
|
|
253
|
+
|
|
254
|
+
<a href=https://github.com/infohlaingbwar/d0rk3r/graphs/contributors>
|
|
255
|
+
<img src=https://contrib.rocks/image?repo=infohlaingbwar/d0rk3r />
|
|
256
|
+
</a>
|
|
257
|
+
|
|
258
|
+
Contributions are welcome! Feel free to open issues or submit PRs.
|
d0rk3r-1.0.0/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# D0RK3R
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<img src="logo.png" alt="D0RK3R Logo" width="600"/>
|
|
6
|
+
|
|
7
|
+
**🔍 Shodan IP scraper with auto-proxy rotation. No API key needed.**
|
|
8
|
+
|
|
9
|
+
[](https://www.python.org/downloads/)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](https://github.com/infohlaingbwar/d0rk3r/stargazers)
|
|
12
|
+
[](https://github.com/infohlaingbwar/d0rk3r/issues)
|
|
13
|
+
[](CONTRIBUTING.md)
|
|
14
|
+
|
|
15
|
+
Perfect for OSINT, bug bounty & pentesting.
|
|
16
|
+
|
|
17
|
+
[Features](#features) • [Install](#install) • [Usage](#usage) • [Examples](#shodan-dork-syntax)
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
✅ **Auto-proxy** — Fetch working proxies from GitHub automatically
|
|
25
|
+
✅ **Proxy rotation** — Bypass Shodan rate limits
|
|
26
|
+
✅ **Smart caching** — Reuse proxies for 6 hours
|
|
27
|
+
✅ **No API key** — Scrapes public Shodan search
|
|
28
|
+
✅ **Fast extraction** — Get 100s-1000s of IPs in seconds
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
36
|
+
cd d0rk3r
|
|
37
|
+
pip install requests[socks]
|
|
38
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Auto-installs `requests` if missing.
|
|
42
|
+
|
|
43
|
+
### Termux
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pkg install python
|
|
47
|
+
pip install requests[socks]
|
|
48
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
49
|
+
cd d0rk3r
|
|
50
|
+
python d0rk3r.py -q "port:443" --auto-proxy
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Kali / Debian / Ubuntu / WSL (PEP 668 error)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip3 install --break-system-packages requests[socks]
|
|
57
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Auto-proxy (recommended)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# CVE hunting
|
|
68
|
+
python3 d0rk3r.py -q "Apache/2.4.49" --auto-proxy -o results.txt
|
|
69
|
+
|
|
70
|
+
# Bug bounty recon
|
|
71
|
+
python3 d0rk3r.py -q 'org:"Tesla Motors"' --auto-proxy --pages 3
|
|
72
|
+
|
|
73
|
+
# IoT devices
|
|
74
|
+
python3 d0rk3r.py -q "port:554 rtsp country:MM" --auto-proxy
|
|
75
|
+
|
|
76
|
+
# Vulnerable hosts
|
|
77
|
+
python3 d0rk3r.py -q "vuln:CVE-2021-41773" --auto-proxy
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Manual proxy file
|
|
81
|
+
|
|
82
|
+
Create `proxy.txt`:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
http://user:pass@1.2.3.4:8080
|
|
86
|
+
socks5://5.6.7.8:1080
|
|
87
|
+
http://9.10.11.12:3128
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
python3 d0rk3r.py -q "port:443" -p proxy.txt --pages 5
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### No proxy (direct)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
python3 d0rk3r.py -q "nginx country:MM"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Shodan Dork Syntax
|
|
105
|
+
|
|
106
|
+
| Syntax | Example | Description |
|
|
107
|
+
|--------|---------|-------------|
|
|
108
|
+
| `port:` | `port:22` | SSH open hosts |
|
|
109
|
+
| `country:` | `country:MM` | Myanmar servers |
|
|
110
|
+
| `city:` | `city:Yangon` | City location |
|
|
111
|
+
| `org:` | `org:"MPT"` | Organization |
|
|
112
|
+
| `hostname:` | `hostname:gov.mm` | Domain names |
|
|
113
|
+
| `os:` | `os:Windows` | Operating system |
|
|
114
|
+
| `product:` | `product:nginx` | Software |
|
|
115
|
+
| `vuln:` | `vuln:CVE-2021-41773` | CVE vulnerable |
|
|
116
|
+
| `http.title:` | `http.title:"admin"` | Page titles |
|
|
117
|
+
| `ssl:` | `ssl:"Myanmar"` | SSL cert info |
|
|
118
|
+
|
|
119
|
+
**Combine queries:**
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
python3 d0rk3r.py -q "Apache/2.4.49 country:MM port:443" --auto-proxy
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Flags
|
|
128
|
+
|
|
129
|
+
| Flag | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `-q` | Shodan dork query (required) |
|
|
132
|
+
| `--auto-proxy` | Auto-fetch proxies from GitHub |
|
|
133
|
+
| `-p` | Path to manual proxy file |
|
|
134
|
+
| `--pages` | Requests per proxy (default: 2) |
|
|
135
|
+
| `--page-max` | Max total requests (0 = auto) |
|
|
136
|
+
| `-o` | Save output to file |
|
|
137
|
+
| `--timeout` | Request timeout in sec (default: 10) |
|
|
138
|
+
| `--delay` | Delay between requests in sec (default: 0.5) |
|
|
139
|
+
| `--no-banner` | Skip banner |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## How It Works
|
|
144
|
+
|
|
145
|
+
### Auto-Proxy
|
|
146
|
+
|
|
147
|
+
1. Fetches fresh proxies from GitHub public lists
|
|
148
|
+
2. Verifies working proxies (tests sample of 100)
|
|
149
|
+
3. Caches proxies for 6 hours
|
|
150
|
+
4. Rotates proxies during scraping
|
|
151
|
+
|
|
152
|
+
### Shodan Bypass
|
|
153
|
+
|
|
154
|
+
Shodan free gives ~2 pages per IP.
|
|
155
|
+
|
|
156
|
+
With proxy rotation:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
Proxy A → page 1 (~300 IPs)
|
|
160
|
+
Proxy B → page 1 (~300 new IPs)
|
|
161
|
+
Proxy C → page 1 (~300 new IPs)
|
|
162
|
+
...
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
10 proxies × 2 pages = 600-3000+ unique IPs.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Example Output
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
$ python3 d0rk3r.py -q "nginx" --auto-proxy --pages 1
|
|
173
|
+
|
|
174
|
+
[*] Auto-fetching proxies...
|
|
175
|
+
[+] Loaded 13 working proxies
|
|
176
|
+
┌─ Proxies : 13
|
|
177
|
+
├─ Requests : 13 (1 per proxy)
|
|
178
|
+
└─ Query : nginx
|
|
179
|
+
|
|
180
|
+
════════════════════════════════════════════════
|
|
181
|
+
✔ 1005 unique IPs │ 1 req OK │ 12 fail │ 55.0s
|
|
182
|
+
════════════════════════════════════════════════
|
|
183
|
+
├─ 101.230.14.203
|
|
184
|
+
├─ 102.182.100.18
|
|
185
|
+
├─ 103.100.84.76
|
|
186
|
+
...
|
|
187
|
+
└─ 1005 total
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Files
|
|
193
|
+
|
|
194
|
+
| File | Purpose |
|
|
195
|
+
|------|---------|
|
|
196
|
+
| `d0rk3r.py` | Main script |
|
|
197
|
+
| `proxy_fetcher.py` | Auto-proxy module |
|
|
198
|
+
| `.proxy_cache.txt` | Cached proxies (auto-generated) |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Note
|
|
203
|
+
|
|
204
|
+
This scrapes Shodan's public web search. IP accuracy is not guaranteed. Always verify results yourself.
|
|
205
|
+
|
|
206
|
+
For educational and authorized testing only.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Contributors
|
|
217
|
+
|
|
218
|
+
<a href=https://github.com/infohlaingbwar/d0rk3r/graphs/contributors>
|
|
219
|
+
<img src=https://contrib.rocks/image?repo=infohlaingbwar/d0rk3r />
|
|
220
|
+
</a>
|
|
221
|
+
|
|
222
|
+
Contributions are welcome! Feel free to open issues or submit PRs.
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: d0rk3r
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Shodan IP scraper with auto-proxy rotation. No API key needed.
|
|
5
|
+
Author-email: Hlaing Bwar <infohlaingbwar@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/infohlaingbwar/d0rk3r
|
|
8
|
+
Project-URL: Documentation, https://www.hlaingbwar.com/articles/d0rk3r-shodan-ip-scraper-bug-bounty
|
|
9
|
+
Project-URL: Repository, https://github.com/infohlaingbwar/d0rk3r
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/infohlaingbwar/d0rk3r/issues
|
|
11
|
+
Keywords: shodan,osint,recon,bug-bounty,pentesting,proxy,scraper,security
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Requires-Python: >=3.7
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: requests[socks]>=2.25.0
|
|
30
|
+
Requires-Dist: beautifulsoup4>=4.9.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
33
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
34
|
+
Requires-Dist: flake8>=4.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# D0RK3R
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
|
|
41
|
+
<img src="logo.png" alt="D0RK3R Logo" width="600"/>
|
|
42
|
+
|
|
43
|
+
**🔍 Shodan IP scraper with auto-proxy rotation. No API key needed.**
|
|
44
|
+
|
|
45
|
+
[](https://www.python.org/downloads/)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://github.com/infohlaingbwar/d0rk3r/stargazers)
|
|
48
|
+
[](https://github.com/infohlaingbwar/d0rk3r/issues)
|
|
49
|
+
[](CONTRIBUTING.md)
|
|
50
|
+
|
|
51
|
+
Perfect for OSINT, bug bounty & pentesting.
|
|
52
|
+
|
|
53
|
+
[Features](#features) • [Install](#install) • [Usage](#usage) • [Examples](#shodan-dork-syntax)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
✅ **Auto-proxy** — Fetch working proxies from GitHub automatically
|
|
61
|
+
✅ **Proxy rotation** — Bypass Shodan rate limits
|
|
62
|
+
✅ **Smart caching** — Reuse proxies for 6 hours
|
|
63
|
+
✅ **No API key** — Scrapes public Shodan search
|
|
64
|
+
✅ **Fast extraction** — Get 100s-1000s of IPs in seconds
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
72
|
+
cd d0rk3r
|
|
73
|
+
pip install requests[socks]
|
|
74
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Auto-installs `requests` if missing.
|
|
78
|
+
|
|
79
|
+
### Termux
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pkg install python
|
|
83
|
+
pip install requests[socks]
|
|
84
|
+
git clone https://github.com/infohlaingbwar/d0rk3r
|
|
85
|
+
cd d0rk3r
|
|
86
|
+
python d0rk3r.py -q "port:443" --auto-proxy
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Kali / Debian / Ubuntu / WSL (PEP 668 error)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip3 install --break-system-packages requests[socks]
|
|
93
|
+
python3 d0rk3r.py -q "port:443" --auto-proxy
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
### Auto-proxy (recommended)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# CVE hunting
|
|
104
|
+
python3 d0rk3r.py -q "Apache/2.4.49" --auto-proxy -o results.txt
|
|
105
|
+
|
|
106
|
+
# Bug bounty recon
|
|
107
|
+
python3 d0rk3r.py -q 'org:"Tesla Motors"' --auto-proxy --pages 3
|
|
108
|
+
|
|
109
|
+
# IoT devices
|
|
110
|
+
python3 d0rk3r.py -q "port:554 rtsp country:MM" --auto-proxy
|
|
111
|
+
|
|
112
|
+
# Vulnerable hosts
|
|
113
|
+
python3 d0rk3r.py -q "vuln:CVE-2021-41773" --auto-proxy
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Manual proxy file
|
|
117
|
+
|
|
118
|
+
Create `proxy.txt`:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
http://user:pass@1.2.3.4:8080
|
|
122
|
+
socks5://5.6.7.8:1080
|
|
123
|
+
http://9.10.11.12:3128
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python3 d0rk3r.py -q "port:443" -p proxy.txt --pages 5
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### No proxy (direct)
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
python3 d0rk3r.py -q "nginx country:MM"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Shodan Dork Syntax
|
|
141
|
+
|
|
142
|
+
| Syntax | Example | Description |
|
|
143
|
+
|--------|---------|-------------|
|
|
144
|
+
| `port:` | `port:22` | SSH open hosts |
|
|
145
|
+
| `country:` | `country:MM` | Myanmar servers |
|
|
146
|
+
| `city:` | `city:Yangon` | City location |
|
|
147
|
+
| `org:` | `org:"MPT"` | Organization |
|
|
148
|
+
| `hostname:` | `hostname:gov.mm` | Domain names |
|
|
149
|
+
| `os:` | `os:Windows` | Operating system |
|
|
150
|
+
| `product:` | `product:nginx` | Software |
|
|
151
|
+
| `vuln:` | `vuln:CVE-2021-41773` | CVE vulnerable |
|
|
152
|
+
| `http.title:` | `http.title:"admin"` | Page titles |
|
|
153
|
+
| `ssl:` | `ssl:"Myanmar"` | SSL cert info |
|
|
154
|
+
|
|
155
|
+
**Combine queries:**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python3 d0rk3r.py -q "Apache/2.4.49 country:MM port:443" --auto-proxy
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Flags
|
|
164
|
+
|
|
165
|
+
| Flag | Description |
|
|
166
|
+
|------|-------------|
|
|
167
|
+
| `-q` | Shodan dork query (required) |
|
|
168
|
+
| `--auto-proxy` | Auto-fetch proxies from GitHub |
|
|
169
|
+
| `-p` | Path to manual proxy file |
|
|
170
|
+
| `--pages` | Requests per proxy (default: 2) |
|
|
171
|
+
| `--page-max` | Max total requests (0 = auto) |
|
|
172
|
+
| `-o` | Save output to file |
|
|
173
|
+
| `--timeout` | Request timeout in sec (default: 10) |
|
|
174
|
+
| `--delay` | Delay between requests in sec (default: 0.5) |
|
|
175
|
+
| `--no-banner` | Skip banner |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## How It Works
|
|
180
|
+
|
|
181
|
+
### Auto-Proxy
|
|
182
|
+
|
|
183
|
+
1. Fetches fresh proxies from GitHub public lists
|
|
184
|
+
2. Verifies working proxies (tests sample of 100)
|
|
185
|
+
3. Caches proxies for 6 hours
|
|
186
|
+
4. Rotates proxies during scraping
|
|
187
|
+
|
|
188
|
+
### Shodan Bypass
|
|
189
|
+
|
|
190
|
+
Shodan free gives ~2 pages per IP.
|
|
191
|
+
|
|
192
|
+
With proxy rotation:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
Proxy A → page 1 (~300 IPs)
|
|
196
|
+
Proxy B → page 1 (~300 new IPs)
|
|
197
|
+
Proxy C → page 1 (~300 new IPs)
|
|
198
|
+
...
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
10 proxies × 2 pages = 600-3000+ unique IPs.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Example Output
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
$ python3 d0rk3r.py -q "nginx" --auto-proxy --pages 1
|
|
209
|
+
|
|
210
|
+
[*] Auto-fetching proxies...
|
|
211
|
+
[+] Loaded 13 working proxies
|
|
212
|
+
┌─ Proxies : 13
|
|
213
|
+
├─ Requests : 13 (1 per proxy)
|
|
214
|
+
└─ Query : nginx
|
|
215
|
+
|
|
216
|
+
════════════════════════════════════════════════
|
|
217
|
+
✔ 1005 unique IPs │ 1 req OK │ 12 fail │ 55.0s
|
|
218
|
+
════════════════════════════════════════════════
|
|
219
|
+
├─ 101.230.14.203
|
|
220
|
+
├─ 102.182.100.18
|
|
221
|
+
├─ 103.100.84.76
|
|
222
|
+
...
|
|
223
|
+
└─ 1005 total
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Files
|
|
229
|
+
|
|
230
|
+
| File | Purpose |
|
|
231
|
+
|------|---------|
|
|
232
|
+
| `d0rk3r.py` | Main script |
|
|
233
|
+
| `proxy_fetcher.py` | Auto-proxy module |
|
|
234
|
+
| `.proxy_cache.txt` | Cached proxies (auto-generated) |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Note
|
|
239
|
+
|
|
240
|
+
This scrapes Shodan's public web search. IP accuracy is not guaranteed. Always verify results yourself.
|
|
241
|
+
|
|
242
|
+
For educational and authorized testing only.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Contributors
|
|
253
|
+
|
|
254
|
+
<a href=https://github.com/infohlaingbwar/d0rk3r/graphs/contributors>
|
|
255
|
+
<img src=https://contrib.rocks/image?repo=infohlaingbwar/d0rk3r />
|
|
256
|
+
</a>
|
|
257
|
+
|
|
258
|
+
Contributions are welcome! Feel free to open issues or submit PRs.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
requirements.txt
|
|
6
|
+
d0rk3r.egg-info/PKG-INFO
|
|
7
|
+
d0rk3r.egg-info/SOURCES.txt
|
|
8
|
+
d0rk3r.egg-info/dependency_links.txt
|
|
9
|
+
d0rk3r.egg-info/entry_points.txt
|
|
10
|
+
d0rk3r.egg-info/requires.txt
|
|
11
|
+
d0rk3r.egg-info/top_level.txt
|
|
12
|
+
d0rk3r_pkg/__init__.py
|
|
13
|
+
d0rk3r_pkg/cli.py
|
|
14
|
+
d0rk3r_pkg/proxy_fetcher.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d0rk3r_pkg
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
D0RK3R - Shodan IP Scraper with Auto-Proxy Rotation
|
|
3
|
+
Author: Hlaing Bwar (https://github.com/infohlaingbwar)
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
__author__ = "Hlaing Bwar"
|
|
8
|
+
__email__ = "infohlaingbwar@gmail.com"
|
|
9
|
+
__license__ = "MIT"
|
|
10
|
+
|
|
11
|
+
from .cli import main
|
|
12
|
+
|
|
13
|
+
__all__ = ["main"]
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# D0RK3R - Shodan Dork IP Extractor
|
|
2
|
+
# Author : https://github.com/infohlaingbwar
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import importlib
|
|
6
|
+
import os
|
|
7
|
+
import random
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
import time
|
|
12
|
+
from urllib.parse import quote
|
|
13
|
+
|
|
14
|
+
def ensure_module(module_name, pip_name=None):
|
|
15
|
+
try:
|
|
16
|
+
return importlib.import_module(module_name)
|
|
17
|
+
except ImportError:
|
|
18
|
+
pkg = pip_name or module_name
|
|
19
|
+
print(f"[+] Installing '{pkg}'...")
|
|
20
|
+
try:
|
|
21
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", pkg])
|
|
22
|
+
except subprocess.CalledProcessError:
|
|
23
|
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "--break-system-packages", pkg])
|
|
24
|
+
return importlib.import_module(module_name)
|
|
25
|
+
|
|
26
|
+
requests = ensure_module("requests", "requests[socks]")
|
|
27
|
+
|
|
28
|
+
VERSION = "1.0"
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
"─".encode(sys.stdout.encoding or "utf-8")
|
|
32
|
+
UNICODE = True
|
|
33
|
+
except (UnicodeEncodeError, UnicodeDecodeError, AttributeError):
|
|
34
|
+
UNICODE = False
|
|
35
|
+
|
|
36
|
+
if UNICODE:
|
|
37
|
+
T_H = "─"
|
|
38
|
+
T_V = "│"
|
|
39
|
+
T_TL = "┌"
|
|
40
|
+
T_BL = "└"
|
|
41
|
+
T_M = "├"
|
|
42
|
+
T_R = "┐"
|
|
43
|
+
T_BR = "┘"
|
|
44
|
+
T_BAR = "═"
|
|
45
|
+
T_OK = "✔"
|
|
46
|
+
T_ERR = "✘"
|
|
47
|
+
else:
|
|
48
|
+
T_H = "-"
|
|
49
|
+
T_V = "|"
|
|
50
|
+
T_TL = "."
|
|
51
|
+
T_BL = "L"
|
|
52
|
+
T_M = "|"
|
|
53
|
+
T_R = "."
|
|
54
|
+
T_BR = "'"
|
|
55
|
+
T_BAR = "="
|
|
56
|
+
T_OK = "+"
|
|
57
|
+
T_ERR = "x"
|
|
58
|
+
|
|
59
|
+
C = {
|
|
60
|
+
"R": "\033[91m",
|
|
61
|
+
"G": "\033[92m",
|
|
62
|
+
"Y": "\033[93m",
|
|
63
|
+
"B": "\033[94m",
|
|
64
|
+
"M": "\033[95m",
|
|
65
|
+
"C": "\033[96m",
|
|
66
|
+
"W": "\033[97m",
|
|
67
|
+
"X": "\033[0m",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
BANNER_ASCII = rf"""{C['R']}
|
|
71
|
+
____ _____ ____ _ ____ _____ ____
|
|
72
|
+
( _ \( _ )( _ \( )/ ___)( _ )( _ \
|
|
73
|
+
)(_) ))(_)(( )(_) )|\___ \ )(_)(( )___/
|
|
74
|
+
(____/(_____)(____/(_)(____/(_____)(__)
|
|
75
|
+
{C['X']}
|
|
76
|
+
{C['C']} D0RK3R - Shodan Dork IP Extractor v{VERSION}{C['X']}
|
|
77
|
+
{C['W']} Author : https://github.com/infohlaingbwar{C['X']}
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
BANNER_UNICODE = rf"""{C['R']}
|
|
81
|
+
██████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██████╗
|
|
82
|
+
╚════██╗██╔═══██╗██╔══██╗██║ ██╔╝╚════██╗██╔══██╗
|
|
83
|
+
█████╔╝██║ ██║██████╔╝█████╔╝ █████╔╝██████╔╝
|
|
84
|
+
██╔═══╝ ██║ ██║██╔══██╗██╔═██╗ ╚═══██╗██╔══██╗
|
|
85
|
+
███████╗╚██████╔╝██║ ██║██║ ██╗██████╔╝██║ ██║
|
|
86
|
+
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝{C['X']}
|
|
87
|
+
{C['C']} D0RK3R - Shodan Dork IP Extractor v{VERSION}{C['X']}
|
|
88
|
+
{C['W']} Author : https://github.com/infohlaingbwar{C['X']}
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
BANNER = BANNER_UNICODE if UNICODE else BANNER_ASCII
|
|
92
|
+
|
|
93
|
+
SHODAN_FACET_URL = "https://www.shodan.io/search/facet?query={q}&facet=ip"
|
|
94
|
+
|
|
95
|
+
USER_AGENTS = [
|
|
96
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
|
|
97
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/17.2 Safari/605.1.15",
|
|
98
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
|
|
99
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0",
|
|
100
|
+
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0",
|
|
101
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Edge/120.0.2210.133",
|
|
102
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) Version/17.2 Mobile/15E148 Safari/604.1",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
IP_RE = re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b")
|
|
106
|
+
|
|
107
|
+
PRIVATE_PREFIXES = (
|
|
108
|
+
"0.", "127.", "169.254.", "172.16.", "172.17.", "172.18.", "172.19.",
|
|
109
|
+
"172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.",
|
|
110
|
+
"172.26.", "172.27.", "172.28.", "172.29.", "172.30.", "172.31.",
|
|
111
|
+
"192.168.", "10.", "224.", "240.",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
DOTS_UNICODE = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
|
|
115
|
+
DOTS_ASCII = "|/-\\"
|
|
116
|
+
DOTS = DOTS_UNICODE if UNICODE else DOTS_ASCII
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def load_proxies(path):
|
|
120
|
+
proxies = []
|
|
121
|
+
if not path or not os.path.isfile(path):
|
|
122
|
+
return proxies
|
|
123
|
+
with open(path) as f:
|
|
124
|
+
for line in f:
|
|
125
|
+
line = line.strip()
|
|
126
|
+
if line and not line.startswith("#"):
|
|
127
|
+
proxies.append(line)
|
|
128
|
+
return proxies
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ProxyRotator:
|
|
132
|
+
def __init__(self, proxies):
|
|
133
|
+
self.proxies = proxies
|
|
134
|
+
self.idx = 0
|
|
135
|
+
|
|
136
|
+
def next(self):
|
|
137
|
+
if not self.proxies:
|
|
138
|
+
return None
|
|
139
|
+
p = self.proxies[self.idx % len(self.proxies)]
|
|
140
|
+
self.idx += 1
|
|
141
|
+
return p
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def is_private(ip):
|
|
145
|
+
return ip.startswith(PRIVATE_PREFIXES)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def is_valid_ip(ip):
|
|
149
|
+
parts = ip.split(".")
|
|
150
|
+
if len(parts) != 4:
|
|
151
|
+
return False
|
|
152
|
+
try:
|
|
153
|
+
return all(0 <= int(p) <= 255 for p in parts)
|
|
154
|
+
except ValueError:
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def extract_ips(html):
|
|
159
|
+
raw = IP_RE.findall(html)
|
|
160
|
+
return [ip for ip in raw if is_valid_ip(ip) and not is_private(ip)]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def request_url(url, proxy, timeout):
|
|
164
|
+
ua = random.choice(USER_AGENTS)
|
|
165
|
+
headers = {"User-Agent": ua}
|
|
166
|
+
proxies_dict = None
|
|
167
|
+
if proxy:
|
|
168
|
+
proxies_dict = {"http": proxy, "https": proxy}
|
|
169
|
+
return requests.get(url, headers=headers, proxies=proxies_dict, timeout=timeout)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def truncate_proxy(p, n=40):
|
|
173
|
+
return (p[:n] + "...") if len(p) > n else p
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def fetch_ips(query, proxies, pages_per_proxy, max_pages, timeout, delay):
|
|
177
|
+
rotator = ProxyRotator(proxies)
|
|
178
|
+
all_ips = set()
|
|
179
|
+
num_proxies = max(len(proxies), 1)
|
|
180
|
+
total_reqs = pages_per_proxy * num_proxies
|
|
181
|
+
if max_pages and max_pages < total_reqs:
|
|
182
|
+
total_reqs = max_pages
|
|
183
|
+
|
|
184
|
+
success = 0
|
|
185
|
+
fails = 0
|
|
186
|
+
start_ts = time.time()
|
|
187
|
+
|
|
188
|
+
for req_num in range(1, total_reqs + 1):
|
|
189
|
+
proxy = rotator.next()
|
|
190
|
+
|
|
191
|
+
url = SHODAN_FACET_URL.format(q=quote(query))
|
|
192
|
+
spinner = DOTS[req_num % len(DOTS)]
|
|
193
|
+
pdisp = truncate_proxy(proxy or "direct")
|
|
194
|
+
status = f"{C['Y']}{spinner}{C['X']} {C['B']}[{req_num}/{total_reqs}]{C['X']} {C['W']}{pdisp}{C['X']} IPs: {C['G']}{len(all_ips)}{C['X']}"
|
|
195
|
+
|
|
196
|
+
if sys.stdout.isatty():
|
|
197
|
+
sys.stdout.write("\r" + " " * 80 + "\r" + status)
|
|
198
|
+
sys.stdout.flush()
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
resp = request_url(url, proxy, timeout)
|
|
202
|
+
if resp.status_code != 200:
|
|
203
|
+
fails += 1
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
ips = extract_ips(resp.text)
|
|
207
|
+
before = len(all_ips)
|
|
208
|
+
all_ips.update(ips)
|
|
209
|
+
success += 1
|
|
210
|
+
|
|
211
|
+
if delay:
|
|
212
|
+
time.sleep(delay)
|
|
213
|
+
except requests.RequestException:
|
|
214
|
+
fails += 1
|
|
215
|
+
continue
|
|
216
|
+
|
|
217
|
+
elapsed = time.time() - start_ts
|
|
218
|
+
|
|
219
|
+
if sys.stdout.isatty():
|
|
220
|
+
sys.stdout.write("\r" + " " * 80 + "\r")
|
|
221
|
+
sys.stdout.flush()
|
|
222
|
+
|
|
223
|
+
return list(all_ips), success, fails, elapsed
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def main():
|
|
227
|
+
parser = argparse.ArgumentParser(
|
|
228
|
+
description="D0RK3R - Shodan Dork IP Extractor",
|
|
229
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
230
|
+
epilog="Examples:\n"
|
|
231
|
+
" python d0rk3r.py -q \"port:443 country:MM\"\n"
|
|
232
|
+
" python d0rk3r.py -q \"port:80\" -p proxy.txt --pages 3\n"
|
|
233
|
+
" python d0rk3r.py -q \"nginx\" -p proxy.txt --page-max 50 -o ips.txt",
|
|
234
|
+
)
|
|
235
|
+
parser.add_argument("-q", "--query", required=True, help="Shodan dork query")
|
|
236
|
+
parser.add_argument("-p", "--proxy", help="Proxy list file (one per line)")
|
|
237
|
+
parser.add_argument("--auto-proxy", action="store_true", help="Auto-fetch proxies from GitHub")
|
|
238
|
+
parser.add_argument("--pages", type=int, default=2, help="Requests per proxy (default: 2)")
|
|
239
|
+
parser.add_argument("--page-max", type=int, default=0, help="Max total requests (0 = auto)")
|
|
240
|
+
parser.add_argument("-o", "--output", help="Output file")
|
|
241
|
+
parser.add_argument("--timeout", type=int, default=10, help="Request timeout in sec")
|
|
242
|
+
parser.add_argument("--delay", type=float, default=0.5, help="Delay between requests in sec")
|
|
243
|
+
parser.add_argument("--no-banner", action="store_true", help="Skip banner")
|
|
244
|
+
args = parser.parse_args()
|
|
245
|
+
|
|
246
|
+
if not args.no_banner:
|
|
247
|
+
print(BANNER)
|
|
248
|
+
|
|
249
|
+
# Auto-fetch proxies if requested
|
|
250
|
+
proxies = []
|
|
251
|
+
if args.auto_proxy:
|
|
252
|
+
try:
|
|
253
|
+
import sys, os
|
|
254
|
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
255
|
+
sys.path.insert(0, script_dir)
|
|
256
|
+
from .proxy_fetcher import get_proxies
|
|
257
|
+
print(f" {C['Y']}[*] Auto-fetching proxies...{C['X']}")
|
|
258
|
+
proxies = get_proxies(verify=True, use_cache=True)
|
|
259
|
+
if proxies:
|
|
260
|
+
print(f" {C['G']}[+] Loaded {len(proxies)} working proxies{C['X']}")
|
|
261
|
+
else:
|
|
262
|
+
print(f" {C['R']}[!] No proxies available{C['X']}")
|
|
263
|
+
except Exception as e:
|
|
264
|
+
print(f" {C['R']}[!] Error: {e}{C['X']}")
|
|
265
|
+
elif args.proxy:
|
|
266
|
+
proxies = load_proxies(args.proxy)
|
|
267
|
+
if proxies:
|
|
268
|
+
print(f" {C['C']}{T_TL}{T_H}{C['X']} Proxies : {C['G']}{len(proxies)}{C['X']}")
|
|
269
|
+
total_est = len(proxies) * args.pages
|
|
270
|
+
print(f" {C['C']}{T_M}{T_H}{C['X']} Requests : {C['G']}{total_est}{C['X']} ({args.pages} per proxy)")
|
|
271
|
+
else:
|
|
272
|
+
print(f" {C['C']}{T_TL}{T_H}{C['X']} Proxies : {C['Y']}none (direct){C['X']}")
|
|
273
|
+
print(f" {C['C']}{T_BL}{T_H}{C['X']} Query : {C['W']}{args.query}{C['X']}\n")
|
|
274
|
+
|
|
275
|
+
max_pages = args.page_max if args.page_max else None
|
|
276
|
+
|
|
277
|
+
ips, success, fails, elapsed = fetch_ips(
|
|
278
|
+
query=args.query,
|
|
279
|
+
proxies=proxies,
|
|
280
|
+
pages_per_proxy=args.pages,
|
|
281
|
+
max_pages=max_pages,
|
|
282
|
+
timeout=args.timeout,
|
|
283
|
+
delay=args.delay,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
if not ips:
|
|
287
|
+
print(f"\n {C['R']}[!] No IPs found{C['X']}")
|
|
288
|
+
sys.exit(1)
|
|
289
|
+
|
|
290
|
+
ips.sort()
|
|
291
|
+
|
|
292
|
+
bar = f"{C['C']}{T_BAR * 48}{C['X']}"
|
|
293
|
+
print(f" {bar}")
|
|
294
|
+
print(f" {C['G']}{T_OK} {len(ips)} unique IPs {C['W']}{T_V}{C['X']} {success} req OK {C['W']}{T_V}{C['X']} {fails} fail {C['W']}{T_V}{C['X']} {elapsed:.1f}s")
|
|
295
|
+
print(f" {bar}")
|
|
296
|
+
|
|
297
|
+
if args.output:
|
|
298
|
+
with open(args.output, "w") as f:
|
|
299
|
+
for ip in ips:
|
|
300
|
+
f.write(ip + "\n")
|
|
301
|
+
print(f" {C['G']}{T_BL}{T_H} Saved {T_R} {C['W']}{args.output}{C['X']}\n")
|
|
302
|
+
|
|
303
|
+
for ip in ips:
|
|
304
|
+
print(f" {C['G']}{T_M}{T_H}{C['X']} {ip}")
|
|
305
|
+
|
|
306
|
+
if ips:
|
|
307
|
+
print(f" {C['G']}{T_BL}{T_H}{C['X']} {C['W']}{len(ips)} total{C['X']}")
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
if __name__ == "__main__":
|
|
311
|
+
main()
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Proxy Auto-Fetcher for D0RK3R
|
|
3
|
+
# Fetches fresh proxies from GitHub public lists
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import time
|
|
7
|
+
import requests
|
|
8
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
9
|
+
|
|
10
|
+
PROXY_SOURCES = [
|
|
11
|
+
"https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/http.txt",
|
|
12
|
+
"https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/socks5.txt",
|
|
13
|
+
"https://raw.githubusercontent.com/clarketm/proxy-list/master/proxy-list-raw.txt",
|
|
14
|
+
"https://raw.githubusercontent.com/ShiftyTR/Proxy-List/master/http.txt",
|
|
15
|
+
"https://raw.githubusercontent.com/ShiftyTR/Proxy-List/master/socks5.txt",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
CACHE_FILE = ".proxy_cache.txt"
|
|
19
|
+
CACHE_TTL = 3600 * 6 # 6 hours
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def fetch_proxies_from_url(url, timeout=10):
|
|
23
|
+
"""Download proxy list from URL"""
|
|
24
|
+
try:
|
|
25
|
+
resp = requests.get(url, timeout=timeout)
|
|
26
|
+
if resp.status_code == 200:
|
|
27
|
+
lines = resp.text.strip().split('\n')
|
|
28
|
+
proxies = []
|
|
29
|
+
for line in lines:
|
|
30
|
+
line = line.strip()
|
|
31
|
+
if line and not line.startswith('#'):
|
|
32
|
+
# Detect protocol
|
|
33
|
+
if '://' not in line:
|
|
34
|
+
# Guess based on source URL
|
|
35
|
+
if 'socks5' in url.lower():
|
|
36
|
+
line = 'socks5://' + line
|
|
37
|
+
elif 'socks4' in url.lower():
|
|
38
|
+
line = 'socks4://' + line
|
|
39
|
+
else:
|
|
40
|
+
line = 'http://' + line
|
|
41
|
+
proxies.append(line)
|
|
42
|
+
return proxies
|
|
43
|
+
except Exception:
|
|
44
|
+
pass
|
|
45
|
+
return []
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def fetch_all_proxies(sources=PROXY_SOURCES, max_workers=5):
|
|
49
|
+
"""Fetch proxies from multiple sources concurrently"""
|
|
50
|
+
all_proxies = []
|
|
51
|
+
|
|
52
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
53
|
+
futures = {executor.submit(fetch_proxies_from_url, url): url for url in sources}
|
|
54
|
+
|
|
55
|
+
for future in as_completed(futures):
|
|
56
|
+
proxies = future.result()
|
|
57
|
+
all_proxies.extend(proxies)
|
|
58
|
+
|
|
59
|
+
# Deduplicate
|
|
60
|
+
return list(set(all_proxies))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_proxy(proxy, test_url="http://www.google.com", timeout=5):
|
|
64
|
+
"""Test if proxy is working"""
|
|
65
|
+
try:
|
|
66
|
+
proxies_dict = {"http": proxy, "https": proxy}
|
|
67
|
+
resp = requests.get(test_url, proxies=proxies_dict, timeout=timeout)
|
|
68
|
+
return resp.status_code == 200
|
|
69
|
+
except Exception:
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def verify_proxies(proxies, max_workers=20, max_test=100):
|
|
74
|
+
"""Verify proxies concurrently (test sample)"""
|
|
75
|
+
# Test only a sample to save time
|
|
76
|
+
sample = proxies[:max_test] if len(proxies) > max_test else proxies
|
|
77
|
+
working = []
|
|
78
|
+
|
|
79
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
80
|
+
futures = {executor.submit(test_proxy, proxy): proxy for proxy in sample}
|
|
81
|
+
|
|
82
|
+
for future in as_completed(futures):
|
|
83
|
+
proxy = futures[future]
|
|
84
|
+
if future.result():
|
|
85
|
+
working.append(proxy)
|
|
86
|
+
|
|
87
|
+
return working
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def load_cached_proxies():
|
|
91
|
+
"""Load proxies from cache if fresh"""
|
|
92
|
+
if not os.path.exists(CACHE_FILE):
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
# Check cache age
|
|
96
|
+
mtime = os.path.getmtime(CACHE_FILE)
|
|
97
|
+
age = time.time() - mtime
|
|
98
|
+
|
|
99
|
+
if age > CACHE_TTL:
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
with open(CACHE_FILE, 'r') as f:
|
|
103
|
+
proxies = [line.strip() for line in f if line.strip()]
|
|
104
|
+
|
|
105
|
+
return proxies if proxies else None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def save_to_cache(proxies):
|
|
109
|
+
"""Save proxies to cache file"""
|
|
110
|
+
with open(CACHE_FILE, 'w') as f:
|
|
111
|
+
for proxy in proxies:
|
|
112
|
+
f.write(proxy + '\n')
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def get_proxies(verify=True, use_cache=True):
|
|
116
|
+
"""Main function: get working proxies"""
|
|
117
|
+
# Try cache first
|
|
118
|
+
if use_cache:
|
|
119
|
+
cached = load_cached_proxies()
|
|
120
|
+
if cached:
|
|
121
|
+
return cached
|
|
122
|
+
|
|
123
|
+
# Fetch from sources
|
|
124
|
+
proxies = fetch_all_proxies()
|
|
125
|
+
|
|
126
|
+
if not proxies:
|
|
127
|
+
return []
|
|
128
|
+
|
|
129
|
+
# Optionally verify
|
|
130
|
+
if verify:
|
|
131
|
+
proxies = verify_proxies(proxies)
|
|
132
|
+
|
|
133
|
+
# Save to cache
|
|
134
|
+
if proxies:
|
|
135
|
+
save_to_cache(proxies)
|
|
136
|
+
|
|
137
|
+
return proxies
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
print("[*] Fetching proxies from GitHub sources...")
|
|
142
|
+
proxies = fetch_all_proxies()
|
|
143
|
+
print(f"[+] Fetched {len(proxies)} proxies")
|
|
144
|
+
|
|
145
|
+
print("[*] Verifying proxies (testing sample of 50)...")
|
|
146
|
+
working = verify_proxies(proxies, max_test=50)
|
|
147
|
+
print(f"[+] {len(working)} working proxies")
|
|
148
|
+
|
|
149
|
+
if working:
|
|
150
|
+
save_to_cache(working)
|
|
151
|
+
print(f"[+] Saved to {CACHE_FILE}")
|
|
152
|
+
for p in working[:10]:
|
|
153
|
+
print(f" {p}")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "d0rk3r"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Shodan IP scraper with auto-proxy rotation. No API key needed."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Hlaing Bwar", email = "infohlaingbwar@gmail.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["shodan", "osint", "recon", "bug-bounty", "pentesting", "proxy", "scraper", "security"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Intended Audience :: Information Technology",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.7",
|
|
23
|
+
"Programming Language :: Python :: 3.8",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Topic :: Security",
|
|
29
|
+
"Topic :: Internet :: WWW/HTTP :: Indexing/Search",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
dependencies = [
|
|
34
|
+
"requests[socks]>=2.25.0",
|
|
35
|
+
"beautifulsoup4>=4.9.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest>=7.0",
|
|
41
|
+
"black>=22.0",
|
|
42
|
+
"flake8>=4.0",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/infohlaingbwar/d0rk3r"
|
|
47
|
+
Documentation = "https://www.hlaingbwar.com/articles/d0rk3r-shodan-ip-scraper-bug-bounty"
|
|
48
|
+
Repository = "https://github.com/infohlaingbwar/d0rk3r"
|
|
49
|
+
"Bug Tracker" = "https://github.com/infohlaingbwar/d0rk3r/issues"
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
d0rk3r = "d0rk3r_pkg.cli:main"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.packages.find]
|
|
55
|
+
where = ["."]
|
|
56
|
+
include = ["d0rk3r_pkg*"]
|
|
57
|
+
exclude = ["tests*", "docs*"]
|
d0rk3r-1.0.0/setup.cfg
ADDED