add --proxy option with SOCKS5 support and remote DNS
Description
This PR introduces a new --proxy option that allows routing all connections through a SOCKS5 proxy with remote DNS resolution (RDNS).
Motivation
Previously, users had to rely on external tools like proxychains to tunnel traffic through a SOCKS5 proxy. This approach had some limitations:
-
Required editing the
proxychains.conffile every time you wanted to switch proxies. -
Not very convenient when running multiple requests with different proxies in a short timeframe.
-
proxychainssupport is limited on Windows, making cross-platform usage harder.
With this PR, you can now simply specify the proxy directly on the CLI per run:
nxc smb 192.168.56.3 -u 'user' -p 'Pass123!' --proxy 127.0.0.1:9000
Benefits
-
No need for proxychains: Configuration is done on the command line no need to edit any config file.
-
Faster switching: Ideal when automating workflows where the proxy might change between requests.
-
Cross-platform support: Fully compatible with Linux, Windows, and macOS no OS-specific hacks required.
-
Remote DNS (RDNS): All hostname resolution happens through the proxy, which is critical in pivoting scenarios or split-DNS environments.
Implementation details
-
Added
--proxyoption to CLI. -
Implemented
_setup_socks_proxy()usingPySocksto monkey-patchsocketand route traffic through the specified proxy. -
Added support for IPv4, IPv6 (
[::1]:PORTsyntax) and optionalsocks5://scheme.
Dependencies
- New dependency:
PySocks>=1.7.1(pure Python, cross-platform, no compilation required)
Type of change
Insert an "x" inside the brackets for relevant items (do not delete options)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Deprecation of feature or functionality
- [ ] This change requires a documentation update
- [ ] This requires a third party update (such as Impacket, Dploot, lsassy, etc)
Screenshots (if appropriate):
Without a proxy, nxc cannot reach the target host (no network route available):
With the new --proxy option, nxc successfully reaches the target through a SOCKS5 proxy (e.g., ssh -D tunnel combined with Ligolo-ng for pivoting):
Checklist:
Insert an "x" inside the brackets for completed and relevant items (do not delete options)
- [X] I have ran Ruff against my changes (via poetry:
poetry run python -m ruff check . --preview, use--fixto automatically fix what it can) - [ ] I have added or updated the
tests/e2e_commands.txtfile if necessary (new modules or features are required to be added to the e2e tests) - [ ] New and existing e2e tests pass locally with my changes
- [ ] If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)
This PR also avoids issues like #906 where proxychains fails on nxc nfs with:
Error during Initialization: [Errno 94] Socket type not supported
With --proxy, NXC establishes the SOCKS5 tunnel at the Python socket level, ensuring all RPC and NFS communication is transparently routed through the proxy Including the initial portmapper lookups which avoids the socket-type errors seen with proxychains :
Very nice, thanks for the PR! Also really great PR style, makes it much easier to understand the intention/benefit of the addition!