socksscope 0.2.0__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.
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: socksscope
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A SOCKS5 front-end that restricts and manages your traffic to keep it inside your engagement scope.
|
|
5
|
+
Project-URL: Homepage, https://github.com/LorenzMap/socksscope
|
|
6
|
+
Project-URL: Repository, https://github.com/LorenzMap/socksscope
|
|
7
|
+
Project-URL: Issues, https://github.com/LorenzMap/socksscope/issues
|
|
8
|
+
Author: LorenzMap
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: dns,pentest,proxy,scope,security,socks5
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Information Technology
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: dnspython>=2.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# socksscope
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/socksscope/)
|
|
30
|
+
[](https://pypi.org/project/socksscope/)
|
|
31
|
+
[](https://github.com/LorenzMap/socksscope/blob/main/LICENSE)
|
|
32
|
+
|
|
33
|
+
A SOCKS5 front-end to better handle and restrict the scope of your traffic during
|
|
34
|
+
an engagement.
|
|
35
|
+
|
|
36
|
+
Wraps a SOCKS5 proxy you already have via --upstream, or acts as a new
|
|
37
|
+
SOCKS5 proxy with --local. Every CONNECT is judged against a ruleset of
|
|
38
|
+
domain names, addresses and ports that is specified as arguments at startup.
|
|
39
|
+
|
|
40
|
+
socksscope additionally allows you to pick where domain names are resolved and
|
|
41
|
+
which DNS server answers them. Through an existing SOCKS5 proxy only DNS via
|
|
42
|
+
TCP can be used for this. See section 'DNS and SOCKS5' below.
|
|
43
|
+
|
|
44
|
+
This tool utilizes [dnspython](https://github.com/rthalley/dnspython).
|
|
45
|
+
|
|
46
|
+
This is a pentesting tool. Only point it at systems and networks you are authorized
|
|
47
|
+
to test.
|
|
48
|
+
|
|
49
|
+
## Why this tool exists
|
|
50
|
+
|
|
51
|
+
- Four reasons to be honest (which are also my personal use-cases)
|
|
52
|
+
- During engagements I always end up with a lot of SOCKS5 proxies (`ssh`,
|
|
53
|
+
[`sshcatch`](https://github.com/LorenzMap/sshcatch), `chisel`, `ligolo`,
|
|
54
|
+
or the C2 directly) so sometimes it makes sense to restrict some of them
|
|
55
|
+
to the network they belong to in order to prevent mistakes (especially
|
|
56
|
+
when coworkers are involved)
|
|
57
|
+
- The network at the other end of a SOCKS5 proxy requires some unique DNS
|
|
58
|
+
settings (just some specific hosts or a specific DNS server) that I don't
|
|
59
|
+
want all other SOCKS5 proxies to share and I don't want to (or cannot)
|
|
60
|
+
reconfigure the jumphost
|
|
61
|
+
- When using a tool via `proxychains` where I can't find a way to deactivate
|
|
62
|
+
telemetry or other default requests that otherwise are sent via the proxy
|
|
63
|
+
- Also I did some experiments with AI agents and wanted to be sure to
|
|
64
|
+
restrict the network connectivity (similar to the first coworker case I guess)
|
|
65
|
+
|
|
66
|
+
- My solution: `socksscope`
|
|
67
|
+
- Open a (local) SOCKS5 proxy that wraps an existing SOCKS5 port or acts standalone
|
|
68
|
+
- Allows you to restrict the connections made through it
|
|
69
|
+
- Specify rules for **domain names, addresses and ports** on the command line or in a file
|
|
70
|
+
- Rate limits and a connection cap that queues instead of dropping
|
|
71
|
+
- Allows a flexible approach to DNS resolving
|
|
72
|
+
- Specify a DNS server to use (also through the tunnel when DNS via TCP is available)
|
|
73
|
+
- Specify domain name mappings like `/etc/hosts`
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
pipx install socksscope # or: pip install socksscope
|
|
79
|
+
socksscope -h
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or from source:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
git clone https://github.com/LorenzMap/socksscope
|
|
86
|
+
cd socksscope
|
|
87
|
+
pip install .
|
|
88
|
+
./socksscope.py -h
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
It is a single file with one dependency (`dnspython`), so copying `socksscope.py`
|
|
92
|
+
onto a host and installing `dnspython` works too.
|
|
93
|
+
|
|
94
|
+
Developed and tested on Python 3.12; needs at least 3.10.
|
|
95
|
+
|
|
96
|
+
## Examples
|
|
97
|
+
|
|
98
|
+
Wrap an SSH dynamic forward, resolve domain names through it and block every connection
|
|
99
|
+
except the ones in the private 10.0.0.0/8 network.
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
# Tunnel
|
|
103
|
+
ssh -ND 1080 user@jumphost
|
|
104
|
+
|
|
105
|
+
# Proxy
|
|
106
|
+
socksscope.py -l 1081 -u 1080 --dns u:10.0.0.53 --allow 10.0.0.0/8
|
|
107
|
+
13:10:11 listening on 127.0.0.1:1081 -> socks 127.0.0.1:1080, dns 10.0.0.53:53/tcp (upstream)
|
|
108
|
+
13:10:11 rule allow * (default)
|
|
109
|
+
13:10:11 rule allow :1-65535 (default)
|
|
110
|
+
13:10:11 rule allow 10.0.0.0/8
|
|
111
|
+
13:10:11
|
|
112
|
+
13:10:11 repeated connections to a host are counted, not logged
|
|
113
|
+
13:10:11 each host is summarised and reset 10s after it goes quiet
|
|
114
|
+
13:10:11 =====================
|
|
115
|
+
...
|
|
116
|
+
|
|
117
|
+
# Client (allowed if intranet.corp.local resolved to an address in 10.0.0.0/8)
|
|
118
|
+
proxychains curl http://intranet.corp.local/
|
|
119
|
+
# or
|
|
120
|
+
curl -x socks5h://127.0.0.1:1081 http://intranet.corp.local/
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Allow web ports only on one domain name. WATCH OUT that this does not block
|
|
124
|
+
IP address connections to the IPs that the domain resolves to! (To restrict
|
|
125
|
+
that use explicit IP address rules or check the --resolve-rules example.)
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
socksscope.py -u 1080 --allow 'corp.local' --allow :80 --allow :443
|
|
129
|
+
13:11:24 listening on 127.0.0.1:1081 -> socks 127.0.0.1:1080, dns upstream
|
|
130
|
+
13:11:24 rule allow 0.0.0.0/0 (default)
|
|
131
|
+
13:11:24 rule allow ::/0 (default)
|
|
132
|
+
13:11:24 rule allow corp.local
|
|
133
|
+
13:11:24 rule allow :80
|
|
134
|
+
13:11:24 rule allow :443
|
|
135
|
+
13:11:24
|
|
136
|
+
13:11:24 repeated connections to a host are counted, not logged
|
|
137
|
+
13:11:24 each host is summarised and reset 10s after it goes quiet
|
|
138
|
+
13:11:24 =====================
|
|
139
|
+
...
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Resolve the names on the local system but send the traffic through the
|
|
143
|
+
tunnel.
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
socksscope.py -u 1080 --dns l:8.8.8.8 --allow '*.corp.local' --allow :443
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Standalone with rate and connection count restrictions.
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
socksscope.py --local --allow 10.10.0.0/16 --rate 1M --max-conns 20
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Check a scope file against a few targets before trusting it.
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
socksscope.py --allow @scope.txt \
|
|
159
|
+
--test-ruleset admin.corp.local:445 \
|
|
160
|
+
--test-ruleset 10.10.0.7 \
|
|
161
|
+
--test-ruleset 8.8.8.8:53
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Only allow connections to the specified domains and enforce that ALSO
|
|
165
|
+
on IP addresses by resolving the domain name rules to their IP addresses.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
socksscope.py -u 1080 --dns u:10.0.0.53 \
|
|
169
|
+
--allow intranet.corp.local --allow fileserver.corp.local \
|
|
170
|
+
--allow :443 --resolve-rules
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## How it works
|
|
174
|
+
|
|
175
|
+
Configure socksscope using command line arguments. See `-h` (short help) and
|
|
176
|
+
`--help` (full help) as well as the examples section above.
|
|
177
|
+
|
|
178
|
+
#### Rules
|
|
179
|
+
|
|
180
|
+
With no rules at all nothing is restricted. `--block` rules obviously
|
|
181
|
+
block all connections to the specified domain names, addresses or ports
|
|
182
|
+
while everything else is allowed.
|
|
183
|
+
On the other hand `--allow` rules block everything except the domain
|
|
184
|
+
names, addresses or ports that are specified.
|
|
185
|
+
**Name, address and port are judged separately and all three have to pass.**
|
|
186
|
+
If multiple rules affect the same domain name, address or port, the rule
|
|
187
|
+
that is the most specific wins (deeper subdomain, smaller subnet).
|
|
188
|
+
An exact tie goes to block.
|
|
189
|
+
|
|
190
|
+
A rule is read from its shape:
|
|
191
|
+
|
|
192
|
+
| value | means |
|
|
193
|
+
| -------------------- | ---------------------------------------- |
|
|
194
|
+
| `corp.local` | the domain name (and all its subdomains) |
|
|
195
|
+
| `*.corp.local` | subdomains only (not the domain root) |
|
|
196
|
+
| `*` | every domain name |
|
|
197
|
+
| `10.0.0.0/8` | a network |
|
|
198
|
+
| `10.0.0.5` | a single address |
|
|
199
|
+
| `10.0.0.1-10.0.0.50` | a range, both ends included |
|
|
200
|
+
| `0.0.0.0/0` | every IPv4 address |
|
|
201
|
+
| `fe80::/64` | a network |
|
|
202
|
+
| `::/0` | every IPv6 address |
|
|
203
|
+
| `:443` | a port |
|
|
204
|
+
| `:8000-8100` | a port range, both ends included |
|
|
205
|
+
|
|
206
|
+
`--allow` and `--block` arguments are repeatable as many times as you want.
|
|
207
|
+
You can specify a `@FILE` that loads a list of rules (one entry per line, `#`
|
|
208
|
+
comments, `!` to negate a rule).
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
# scope.txt given as '--allow @scope.txt'
|
|
212
|
+
corp.local
|
|
213
|
+
10.10.0.0/16
|
|
214
|
+
192.168.1.10-192.168.1.50
|
|
215
|
+
!192.168.1.42 # excluded host
|
|
216
|
+
:443
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`--test-ruleset` shows the whole decision without opening a listener:
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
$ socksscope.py --local --allow 'corp.local' --allow :443 --block admin.corp.local \
|
|
223
|
+
--test-ruleset www.corp.local --test-ruleset www.corp.local:443 --test-ruleset admin.corp.local:443
|
|
224
|
+
=====================
|
|
225
|
+
|
|
226
|
+
www.corp.local:80 => DENY (port not allowed by ruleset)
|
|
227
|
+
www.corp.local:443 => ALLOW -> www.corp.local
|
|
228
|
+
admin.corp.local:443 => DENY (block admin.corp.local)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
When using `--test-ruleset` you may be asked whether DNS queries should be sent to
|
|
232
|
+
resolve the domain names. Read the question, think about whether queries like that are
|
|
233
|
+
acceptable in your engagement, and then answer.
|
|
234
|
+
|
|
235
|
+
#### DNS
|
|
236
|
+
|
|
237
|
+
This subsection describes what the different DNS arguments do. One important note
|
|
238
|
+
first:
|
|
239
|
+
|
|
240
|
+
**Where a domain name gets resolved decides how effective some rules are!**
|
|
241
|
+
For example, using an upstream SOCKS5 without specifying a `--dns` resolves the
|
|
242
|
+
domain names on the upstream, so socksscope cannot enforce its address rules for that
|
|
243
|
+
request. The section 'DNS and SOCKS5' below explains why this happens and why for
|
|
244
|
+
this upstream use-case only DNS via TCP can be used.
|
|
245
|
+
|
|
246
|
+
If you want to skip that problem entirely and don't need domain name resolution at all:
|
|
247
|
+
`--block '*'` refuses every domain name, so every request has to carry an address
|
|
248
|
+
and the address rules apply to all of them.
|
|
249
|
+
|
|
250
|
+
`--dns` says which side of the tunnel a domain name is resolved on and,
|
|
251
|
+
optionally, which server to ask over there:
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
--dns SIDE[:SERVER[:PORT][:tcp|udp]]
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The side is `u` (`upstream`) or `l` (`local`). Without a `SERVER` the default
|
|
258
|
+
system configuration of the specified side is used. If `SERVER` is specified
|
|
259
|
+
socksscope queries the DNS itself.
|
|
260
|
+
|
|
261
|
+
| `--dns` | who answers | the query goes | transport |
|
|
262
|
+
| ------------------ | ----------------------------------- | ----------------------------------------- | --------- |
|
|
263
|
+
| *(nothing)* | `u`, or `l` with `--local` | | |
|
|
264
|
+
| `u` | the upstream's resolver | upstream's default configuration | - |
|
|
265
|
+
| `l` | local system's resolver | local system's default configuration | - |
|
|
266
|
+
| `u:10.0.0.53` | socksscope via 10.0.0.53 | through the tunnel | tcp |
|
|
267
|
+
| `u:10.0.0.53:tcp` | socksscope via 10.0.0.53 | through the tunnel | tcp |
|
|
268
|
+
| `u:[::1]:5353:tcp` | socksscope via `::1` on port 5353 | through the tunnel | tcp |
|
|
269
|
+
| `u:10.0.0.53:udp` | refused, see 'DNS and SOCKS5' below | | |
|
|
270
|
+
| `l:8.8.8.8` | socksscope via 8.8.8.8 | local system's network | udp |
|
|
271
|
+
| `l:8.8.8.8:udp` | socksscope via 8.8.8.8 | local system's network | udp |
|
|
272
|
+
| `l:8.8.8.8:tcp` | socksscope via 8.8.8.8 | local system's network | tcp |
|
|
273
|
+
| `l:8.8.8.8:5353` | socksscope via 8.8.8.8 on port 5353 | local system's network | udp |
|
|
274
|
+
|
|
275
|
+
`SERVER` must be an address, never a domain name. Resolving the resolver would need
|
|
276
|
+
a resolver, and which side should answer *that* question is exactly the
|
|
277
|
+
confusion this argument exists to remove. Look it up once yourself instead:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
dig +short dns.corp.local # from here
|
|
281
|
+
proxychains dig +tcp +short dns.corp.local # from the other end of the tunnel
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Additionally: The tool you use through socksscope has to hand the domain name to the proxy
|
|
285
|
+
instead of trying to resolve it itself. For example, use `socks5h://` with curl and set
|
|
286
|
+
`network.proxy.socks_remote_dns = true` in Firefox if you have trouble.
|
|
287
|
+
|
|
288
|
+
#### Hosts Mapping
|
|
289
|
+
|
|
290
|
+
`--hosts` is checked before all of the DNS handling and answers without any query. It takes
|
|
291
|
+
mappings of `name=ADDRESS` or `'ADDRESS name [name ...]'`. Files can be specified (similar to `/etc/hosts`).
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
--hosts intranet.corp.local=10.0.0.7
|
|
295
|
+
--hosts "10.0.0.8 db.corp.local db"
|
|
296
|
+
--hosts @hosts.txt
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
#### Resolve Rules
|
|
300
|
+
|
|
301
|
+
By default domain name rules only restrict the domain name and do not affect
|
|
302
|
+
IP address rules. For example, a host may be blocked by a domain name rule but
|
|
303
|
+
still be reachable by its IP.
|
|
304
|
+
|
|
305
|
+
`--resolve-rules` solves that. Every domain name rule is resolved at startup
|
|
306
|
+
and again at a fixed interval (`--resolve-rules-every`, 300s by default) so
|
|
307
|
+
socksscope can apply the addresses received as address rules. A blocked domain
|
|
308
|
+
name then blocks its addresses too. Works with `--test-ruleset` as well.
|
|
309
|
+
Resolving like this needs a resolver of our own, so anything but a plain
|
|
310
|
+
`--dns u`. Wildcard rules (`*.corp.local`, `*`) cannot be resolved and stay
|
|
311
|
+
name-only, socksscope says so at startup.
|
|
312
|
+
|
|
313
|
+
`--resolve-rules` results in active traffic to the specified DNS server! So it's
|
|
314
|
+
probably best to use it only against public DNS servers, or internal ones where you
|
|
315
|
+
know this is acceptable during an engagement. socksscope asks before it sends the
|
|
316
|
+
first queries, `--yes-resolve-rules` answers that prompt for you.
|
|
317
|
+
|
|
318
|
+
#### Connection Limits
|
|
319
|
+
|
|
320
|
+
`--rate` is one budget shared by all connections, `--rate-per-conn` gives every
|
|
321
|
+
connection its own. Both take bytes per second in a `1M` or `512k` style.
|
|
322
|
+
|
|
323
|
+
`--max-conns` caps how many connections run at the same time. The rest queue
|
|
324
|
+
instead of failing, a waiting client simply sits in the SOCKS5 handshake without
|
|
325
|
+
a reply until a slot frees up. `--queue-timeout` limits how long it waits there.
|
|
326
|
+
|
|
327
|
+
## DNS and SOCKS5
|
|
328
|
+
|
|
329
|
+
While the tool feels intuitive in most aspects (at least to me), one stands
|
|
330
|
+
out as confusing and I want to give some explanation for it.
|
|
331
|
+
|
|
332
|
+
The SOCKS5 protocol supports UDP, but most endpoints/servers do not (including
|
|
333
|
+
`ssh -D` for example) (2026-08). Accordingly, DNS requests through SOCKS5 proxies
|
|
334
|
+
are not sent as UDP requests from the client through the tunnel. Instead the
|
|
335
|
+
domain name itself is sent in place of an IP address in the CONNECT request. The
|
|
336
|
+
endpoint/server receives it, resolves the domain name using its own configuration
|
|
337
|
+
or cache, and then establishes the TCP connection to the destination.
|
|
338
|
+
|
|
339
|
+
For the domain name rules and host to IP mapping of socksscope this is fine
|
|
340
|
+
because we can simply read that domain name from the CONNECT request.
|
|
341
|
+
|
|
342
|
+
However, every time we want to actively resolve something through the tunnel
|
|
343
|
+
using our own local logic we are limited to DNS via TCP requests. This affects
|
|
344
|
+
the DNS queries of your tools as well as those from `--resolve-rules`, resulting
|
|
345
|
+
in the limitation that `--dns u:SERVER:udp` is refused at startup. Asking over UDP
|
|
346
|
+
means asking from here, which is `--dns l:SERVER` - the data still goes through
|
|
347
|
+
the upstream, only the query does not.
|
|
348
|
+
|
|
349
|
+
## Word of Warning
|
|
350
|
+
|
|
351
|
+
**socksscope is not a firewall or privacy tool.** It only sees what a client
|
|
352
|
+
sends through it. Nothing stops a client from opening a socket directly,
|
|
353
|
+
so the scope is enforced on the tools you point at it, not on the host.
|
|
354
|
+
While it's possible to use socksscope securely, it is a pentesting/redteaming
|
|
355
|
+
tool and NOT a privacy tool. There are a lot of ways to misconfigure socksscope!
|
|
356
|
+
|
|
357
|
+
**`--resolve-rules` can be noisy.** It queries every domain name rule again and
|
|
358
|
+
again in fixed intervals. That is fine against a public DNS server, but may
|
|
359
|
+
not be against an internal one that somebody is watching.
|
|
360
|
+
|
|
361
|
+
**It fails closed.** A domain name rule that cannot be resolved at startup stops
|
|
362
|
+
the tool, and so does a domain name rule that stays unconfirmable for three refresh
|
|
363
|
+
intervals. Better than judging traffic by an address we cannot verify.
|
|
364
|
+
|
|
365
|
+
## Options
|
|
366
|
+
|
|
367
|
+
`socksscope.py -h` prints a short help with the arguments needed to get going.
|
|
368
|
+
The full reference below is `socksscope.py --help`.
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
usage: socksscope.py [-h] [--help] [-l [HOST:]PORT] [--listen-auth USER:PASS]
|
|
372
|
+
[--local] [-u [HOST:]PORT] [--upstream-auth USER:PASS]
|
|
373
|
+
[-v] [-q] [--version] [--allow RULE] [--block RULE]
|
|
374
|
+
[--test-ruleset HOST[:PORT]] [--resolve-rules]
|
|
375
|
+
[--yes-resolve-rules] [--resolve-rules-every SEC]
|
|
376
|
+
[--dns SIDE[:SERVER[:PORT][:tcp|udp]]] [--hosts ENTRY]
|
|
377
|
+
[--rate SIZE] [--rate-per-conn SIZE] [--max-conns N]
|
|
378
|
+
[--queue-timeout SEC]
|
|
379
|
+
|
|
380
|
+
socksscope - a SOCKS5 front-end that lets you manage your traffic and keep it
|
|
381
|
+
inside your engagement scope. Can wrap an existing SOCKS5 port (--upstream)
|
|
382
|
+
or act independently (--local).
|
|
383
|
+
|
|
384
|
+
Every CONNECT is judged against a ruleset of domain names, addresses and ports,
|
|
385
|
+
given as arguments or in files at startup. Additionally you can specify a DNS
|
|
386
|
+
server to use and throttle connection speeds.
|
|
387
|
+
|
|
388
|
+
While it's possible to use socksscope securely, this is a pentesting/redteaming
|
|
389
|
+
tool and NOT a privacy tool. There are a lot of ways to misconfigure socksscope!
|
|
390
|
+
Watch out for unexpected rulesets when combining IP address and domain name rules.
|
|
391
|
+
(Check the README on Github for more information!)
|
|
392
|
+
|
|
393
|
+
options:
|
|
394
|
+
-h show a short help message and exit
|
|
395
|
+
--help show the full help and exit
|
|
396
|
+
-l [HOST:]PORT, --listen [HOST:]PORT
|
|
397
|
+
SOCKS5 port socksscope.py opens (default:
|
|
398
|
+
127.0.0.1:1081) - (restricted) SOCKS5 port where the
|
|
399
|
+
client programs connect to
|
|
400
|
+
--listen-auth USER:PASS
|
|
401
|
+
optional credentials for the SOCKS5 port socksscope
|
|
402
|
+
opens
|
|
403
|
+
--local no SOCKS5 proxy to wrap, run socksscope.py
|
|
404
|
+
independently - connect out from this host while
|
|
405
|
+
enforcing the ruleset
|
|
406
|
+
-u [HOST:]PORT, --upstream [HOST:]PORT
|
|
407
|
+
the existing SOCKS5 proxy that will be wrapped
|
|
408
|
+
(default: 127.0.0.1:1080)
|
|
409
|
+
--upstream-auth USER:PASS
|
|
410
|
+
optional credentials for the upstream proxy
|
|
411
|
+
-v, --verbose log every connection with additional information
|
|
412
|
+
-q, --quiet log warnings only
|
|
413
|
+
--version show the version and exit
|
|
414
|
+
|
|
415
|
+
ruleset:
|
|
416
|
+
--allow RULE domain name, IP address or port rule to allow
|
|
417
|
+
(repeatable) - Rules: domain.tld | *.domain.tld | * |
|
|
418
|
+
IP | IP/NET | IP-IP | :PORT | :PORT-PORT - @FILE loads
|
|
419
|
+
a rules file - ranges include both ends - '!' inverts
|
|
420
|
+
a rule
|
|
421
|
+
--block RULE same as --allow but blocked instead (repeatable) -
|
|
422
|
+
syntax exactly like --allow
|
|
423
|
+
--test-ruleset HOST[:PORT]
|
|
424
|
+
print how a target would be judged, then exit
|
|
425
|
+
(repeatable) - a target without a PORT is judged as
|
|
426
|
+
:80
|
|
427
|
+
--resolve-rules resolve domain name rules and apply them as IP address
|
|
428
|
+
rules (results in repeating queries)
|
|
429
|
+
--yes-resolve-rules answer the startup --resolve-rules confirmation with
|
|
430
|
+
yes
|
|
431
|
+
--resolve-rules-every SEC
|
|
432
|
+
interval to re-resolve domain name rules (see
|
|
433
|
+
--resolve-rules) - if a domain name rule is
|
|
434
|
+
unconfirmed for three intervals socksscope exits - use
|
|
435
|
+
0 to resolve only once at startup (default: 300)
|
|
436
|
+
|
|
437
|
+
DNS:
|
|
438
|
+
--dns SIDE[:SERVER[:PORT][:tcp|udp]]
|
|
439
|
+
specify where DNS queries should be resolved and what
|
|
440
|
+
protocol to use - check the README on Github for
|
|
441
|
+
explanations of all combinations - SIDE=[u|upstream]
|
|
442
|
+
to resolve through the wrapped SOCKS5 - SIDE=[l|local]
|
|
443
|
+
to resolve via the host socksscope is running on -
|
|
444
|
+
[:SERVER[:PORT]] optionally specify a DNS server -
|
|
445
|
+
[:tcp|:udp] optionally specify the DNS transport
|
|
446
|
+
protocol
|
|
447
|
+
--hosts ENTRY static mapping used before any DNS (like /etc/hosts)
|
|
448
|
+
(repeatable) - 'name=ADDRESS' or 'ADDRESS name' or
|
|
449
|
+
'@FILE' to load a list
|
|
450
|
+
|
|
451
|
+
limits:
|
|
452
|
+
--rate SIZE total bytes/s over all connections (e.g. 1M, 512k)
|
|
453
|
+
--rate-per-conn SIZE bytes/s for a single connection
|
|
454
|
+
--max-conns N connections to run at once - the rest queue instead of
|
|
455
|
+
failing
|
|
456
|
+
--queue-timeout SEC give up queueing after this long, 0 waits forever
|
|
457
|
+
(default: 60)
|
|
458
|
+
|
|
459
|
+
For more detailed examples, reasonings behind design decisions as well as an in-depth
|
|
460
|
+
explanation of socksscope's DNS resolving (especially when wrapping a SOCKS5 port and
|
|
461
|
+
actively resolving domain name rules using --resolve-rules) check the README on Github.
|
|
462
|
+
|
|
463
|
+
examples:
|
|
464
|
+
socksscope.py -u 1080 --dns u:10.0.0.53 --allow @scope.txt
|
|
465
|
+
socksscope.py -u 1080 --resolve-rules --allow 'intranet.corp.local' --allow :443
|
|
466
|
+
socksscope.py --local --allow 10.0.0.0/8 --rate 1M --max-conns 20
|
|
467
|
+
socksscope.py --allow @scope.txt --test-ruleset admin.corp.local:445
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Testing
|
|
471
|
+
|
|
472
|
+
- the test suite lives in `tests/` (pytest)
|
|
473
|
+
- run it from a virtualenv with the project and its dev dependencies installed
|
|
474
|
+
(`pip install -e .`, then `pip install --group dev` on pip 25.1+ or simply
|
|
475
|
+
`pip install pytest pytest-xdist coverage`)
|
|
476
|
+
- run it via `python -m pytest` or `tests/test.sh`, `-n 8` runs it in parallel
|
|
477
|
+
- for the coverage of the tests run `tests/test.sh cov`
|
|
478
|
+
- the throttling tests are timing based, so a busy machine can make them flap;
|
|
479
|
+
re-run before believing a failure there
|
|
480
|
+
|
|
481
|
+
## License
|
|
482
|
+
|
|
483
|
+
MIT
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
socksscope.py,sha256=r0LDOe_ACSUYQXAhQLwJUYDuRwFZXQvOyBwTWZJRs7I,62923
|
|
2
|
+
socksscope-0.2.0.dist-info/METADATA,sha256=wks7QFuAyv18el0G8Uc_JGpMwj2mUTgJTTmTh4Dje3o,22141
|
|
3
|
+
socksscope-0.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
4
|
+
socksscope-0.2.0.dist-info/entry_points.txt,sha256=LPoac2ZY7fTFEV05pIoUo6amLQw88sZsDFAFqTCTB_0,47
|
|
5
|
+
socksscope-0.2.0.dist-info/licenses/LICENSE,sha256=93O_1lhlvOC-EguDWXlZrhtzjsoKQ5_8JwTj5BYVP5U,1066
|
|
6
|
+
socksscope-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LorenzMap
|
|
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.
|