2021-09-02 11:30:23 +02:00
|
|
|
# tun2proxy
|
2023-03-26 00:18:28 +01:00
|
|
|
A tunnel interface for HTTP and SOCKS proxies on Linux based on [smoltcp](https://github.com/smoltcp-rs/smoltcp).
|
2021-09-02 11:30:23 +02:00
|
|
|
|
2023-07-01 22:17:25 +02:00
|
|
|
## Features
|
|
|
|
- HTTP proxy support (unauthenticated, basic and digest auth)
|
|
|
|
- SOCKS4 and SOCKS5 support (unauthenticated, username/password auth)
|
|
|
|
- SOCKS4a and SOCKS5h support (through the virtual DNS feature)
|
|
|
|
- Minimal configuration setup for routing all traffic
|
|
|
|
- IPv4 and IPv6 support
|
|
|
|
- GFW evasion mechanism for certain use cases (see [issue #35](https://github.com/blechschmidt/tun2proxy/issues/35))
|
2023-08-20 19:58:30 +02:00
|
|
|
- SOCKS5 UDP support
|
2023-08-31 15:59:07 +08:00
|
|
|
- Native support for proxying DNS over TCP
|
2023-07-01 22:17:25 +02:00
|
|
|
|
2021-09-02 11:30:23 +02:00
|
|
|
## Build
|
|
|
|
Clone the repository and `cd` into the project folder. Then run the following:
|
|
|
|
```
|
|
|
|
cargo build --release
|
|
|
|
```
|
|
|
|
|
|
|
|
## Setup
|
2023-03-26 00:18:28 +01:00
|
|
|
## Automated Setup
|
|
|
|
Using `--setup auto`, you can have tun2proxy configure your system to automatically route all traffic through the
|
|
|
|
specified proxy. This requires running the tool as root and will roughly perform the steps outlined in the section
|
|
|
|
describing the manual setup, except that a bind mount is used to overlay the `/etc/resolv.conf` file.
|
|
|
|
|
2023-03-26 16:30:30 +02:00
|
|
|
You would then run the tool as follows:
|
|
|
|
```bash
|
2023-04-16 10:28:52 +02:00
|
|
|
sudo ./target/release/tun2proxy --setup auto --proxy "socks5://1.2.3.4:1080"
|
2023-03-26 16:30:30 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
Apart from SOCKS5, SOCKS4 and HTTP are supported.
|
|
|
|
|
|
|
|
Note that if your proxy is a non-global IP address (e.g. because the proxy is provided by some tunneling tool running
|
|
|
|
locally), you will additionally need to provide the public IP address of the server through which the traffic is
|
2023-07-23 02:03:15 +08:00
|
|
|
actually tunneled. In such a case, the tool will tell you to specify the address through `--bypass-ip <address>` if you
|
2023-03-26 16:30:30 +02:00
|
|
|
wish to make use of the automated setup feature.
|
|
|
|
|
2023-03-26 00:18:28 +01:00
|
|
|
## Manual Setup
|
2021-09-02 11:30:23 +02:00
|
|
|
A standard setup, which would route all traffic from your system through the tunnel interface, could look as follows:
|
2022-08-17 00:04:08 +02:00
|
|
|
```shell
|
2023-03-25 01:53:30 +01:00
|
|
|
# The proxy type can be either SOCKS4, SOCKS5 or HTTP.
|
2023-03-22 12:08:07 +01:00
|
|
|
PROXY_TYPE=SOCKS5
|
2022-08-17 00:04:08 +02:00
|
|
|
PROXY_IP=1.2.3.4
|
|
|
|
PROXY_PORT=1080
|
2023-07-23 02:03:15 +08:00
|
|
|
BYPASS_IP=123.45.67.89
|
2022-08-17 00:04:08 +02:00
|
|
|
|
2023-03-22 12:08:07 +01:00
|
|
|
# Create a tunnel interface named tun0 which your user can bind to,
|
|
|
|
# so we don't need to run tun2proxy as root.
|
2021-09-02 11:30:23 +02:00
|
|
|
sudo ip tuntap add name tun0 mode tun user $USER
|
|
|
|
sudo ip link set tun0 up
|
|
|
|
|
2023-03-22 12:08:07 +01:00
|
|
|
# To prevent a routing loop, we add a route to the proxy server that behaves
|
|
|
|
# like the default route.
|
2023-07-23 02:03:15 +08:00
|
|
|
sudo ip route add "$BYPASS_IP" $(ip route | grep '^default' | cut -d ' ' -f 2-)
|
2021-09-02 11:30:23 +02:00
|
|
|
|
|
|
|
# Route all your traffic through tun0 without interfering with the default route.
|
2021-09-03 15:12:13 +02:00
|
|
|
sudo ip route add 128.0.0.0/1 dev tun0
|
2021-09-02 11:30:23 +02:00
|
|
|
sudo ip route add 0.0.0.0/1 dev tun0
|
|
|
|
|
2023-03-24 22:28:59 +01:00
|
|
|
# If you wish to also route IPv6 traffic through the proxy, these two commands will do.
|
|
|
|
sudo ip route add ::/1 dev tun0
|
|
|
|
sudo ip route add 8000::/1 dev tun0
|
|
|
|
|
2023-03-25 15:20:31 +01:00
|
|
|
# Make sure that DNS queries are routed through the tunnel.
|
|
|
|
sudo sh -c "echo nameserver 198.18.0.1 > /etc/resolv.conf"
|
|
|
|
|
2023-03-22 12:08:07 +01:00
|
|
|
./target/release/tun2proxy --tun tun0 --proxy "$PROXY_TYPE://$PROXY_IP:$PROXY_PORT"
|
2021-09-02 11:30:23 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
Note that if you paste these commands into a shell script, which you then run with `sudo`, you might want to replace
|
|
|
|
`$USER` with `$SUDO_USER`.
|
|
|
|
|
2023-03-23 22:44:04 +01:00
|
|
|
This tool implements a virtual DNS feature that is used by default. When a DNS packet to port 53 is detected, an IP
|
|
|
|
address from `198.18.0.0/15` is chosen and mapped to the query name. Connections destined for an IP address from that
|
|
|
|
range will supply the proxy with the mapped query name instead of the IP address. Since many proxies do not support UDP,
|
|
|
|
this enables an out-of-the-box experience in most cases, without relying on third-party resolvers or applications.
|
|
|
|
Depending on your use case, you may want to disable this feature using `--dns none`.
|
|
|
|
In that case, you might need an additional tool like [dnsproxy](https://github.com/AdguardTeam/dnsproxy) that is
|
|
|
|
configured to listen on a local UDP port and communicates with a third-party upstream DNS server via TCP.
|
2022-08-17 00:04:08 +02:00
|
|
|
|
2023-03-22 12:08:07 +01:00
|
|
|
When you terminate this program and want to eliminate the impact caused by the above several commands,
|
|
|
|
you can execute the following command. The routes will be automatically deleted with the tunnel device.
|
2023-03-22 10:24:55 +08:00
|
|
|
```shell
|
2023-03-22 12:08:07 +01:00
|
|
|
sudo ip link del tun0
|
2023-03-22 10:24:55 +08:00
|
|
|
```
|
|
|
|
|
2021-09-02 11:30:23 +02:00
|
|
|
## CLI
|
|
|
|
```
|
|
|
|
Tunnel interface to proxy.
|
|
|
|
|
2023-03-22 12:08:07 +01:00
|
|
|
Usage: tun2proxy [OPTIONS] --proxy <URL>
|
2021-09-02 11:30:23 +02:00
|
|
|
|
2023-03-20 14:16:07 +08:00
|
|
|
Options:
|
2023-08-31 16:11:35 +08:00
|
|
|
-t, --tun <name> Name of the tun interface [default: tun0]
|
|
|
|
--tun-fd <fd> File descriptor of the tun interface
|
|
|
|
--tun-mtu <mtu> MTU of the tun interface (only with tunnel file descriptor) [default: 1500]
|
|
|
|
-p, --proxy <URL> Proxy URL in the form proto://[username[:password]@]host:port
|
|
|
|
-d, --dns <strategy> DNS handling strategy [default: virtual] [possible values: virtual, over-tcp, direct]
|
|
|
|
--dns-addr <IP> DNS resolver address [default: 8.8.8.8]
|
|
|
|
-6, --ipv6-enabled IPv6 enabled
|
2023-10-23 09:44:27 +08:00
|
|
|
-s, --setup <method> Routing and system setup [default: none] [possible values: none, auto]
|
2023-10-29 23:01:06 +01:00
|
|
|
-b, --bypass <IP|CIDR> IPs and CIDRs used in routing setup which should bypass the tunnel
|
2023-08-31 16:11:35 +08:00
|
|
|
-v, --verbosity <level> Verbosity level [default: info] [possible values: off, error, warn, info, debug, trace]
|
|
|
|
-h, --help Print help
|
|
|
|
-V, --version Print version
|
2022-08-17 00:04:08 +02:00
|
|
|
```
|
2023-03-25 01:53:30 +01:00
|
|
|
Currently, tun2proxy supports HTTP, SOCKS4/SOCKS4a and SOCKS5. A proxy is supplied to the `--proxy` argument in the
|
2023-03-22 16:24:41 +01:00
|
|
|
URL format. For example, an HTTP proxy at `1.2.3.4:3128` with a username of `john.doe` and a password of `secret` is
|
|
|
|
supplied as `--proxy http://john.doe:secret@1.2.3.4:3128`. This works analogously to curl's `--proxy` argument.
|
2022-08-17 00:04:08 +02:00
|
|
|
|
2023-08-30 14:59:54 +08:00
|
|
|
## Docker Support
|
2023-10-01 19:37:33 +02:00
|
|
|
Tun2proxy can serve as a proxy for other Docker containers. To make use of that feature, first build the image:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
docker build -t tun2proxy .
|
|
|
|
```
|
|
|
|
|
|
|
|
Next, start a container from the tun2proxy image:
|
2023-08-30 14:59:54 +08:00
|
|
|
|
|
|
|
```bash
|
|
|
|
docker run -d \
|
|
|
|
-v /dev/net/tun:/dev/net/tun \
|
|
|
|
--sysctl net.ipv6.conf.default.disable_ipv6=0 \
|
|
|
|
--cap-add NET_ADMIN \
|
|
|
|
--name tun2proxy \
|
2023-10-29 23:01:06 +01:00
|
|
|
tun2proxy --proxy proto://[username[:password]@]host:port
|
2023-08-30 14:59:54 +08:00
|
|
|
```
|
|
|
|
|
2023-10-10 16:04:13 +08:00
|
|
|
You can then provide the running container's network to another worker container by sharing the network namespace (like kubernetes sidecar):
|
2023-08-30 14:59:54 +08:00
|
|
|
|
|
|
|
```bash
|
|
|
|
docker run -it \
|
|
|
|
--network "container:tun2proxy" \
|
2023-10-01 19:37:33 +02:00
|
|
|
ubuntu:latest
|
2023-08-30 14:59:54 +08:00
|
|
|
```
|
|
|
|
|
2023-03-24 22:28:59 +01:00
|
|
|
## Configuration Tips
|
|
|
|
### DNS
|
|
|
|
When DNS resolution is performed by a service on your machine or through a server in your local network, DNS resolution
|
|
|
|
will not be performed through the tunnel interface, since the routes to localhost or your local network are more
|
|
|
|
specific than `0.0.0.0/1` and `128.0.0.0/1`.
|
|
|
|
In this case, it may be advisable to update your `/etc/resolv.conf` file to use a nameserver address that is routed
|
|
|
|
through the tunnel interface. When virtual DNS is working correctly, you will see log messages like
|
|
|
|
`DNS query: example.org` for hostnames which your machine is connecting to after having resolved them through DNS.
|
|
|
|
|
|
|
|
Note that software like the `NetworkManager` may change the `/etc/resolv.conf` file automatically at any time, which
|
|
|
|
will result in DNS leaks. A hacky solution to prevent this consists in making the file immutable as follows:
|
|
|
|
`sudo chattr +i "$(realpath /etc/resolv.conf)"`.
|
|
|
|
|
|
|
|
### IPv6
|
|
|
|
Some proxy servers might not support IPv6. When using virtual DNS, this is not a problem as DNS names are resolved by
|
|
|
|
the proxy server. When DNS names are resolved to IPv6 addresses locally, this becomes a problem as the proxy will be
|
|
|
|
asked to open connections to IPv6 destinations. In such a case, you can disable IPv6 on your machine. This can be done
|
|
|
|
either through `sysctl -w net.ipv6.conf.all.disable_ipv6=1` and `sysctl -w net.ipv6.conf.default.disable_ipv6=1`
|
|
|
|
or through `ip -6 route del default`, which causes the `libc` resolver (and other software) to not issue DNS AAAA
|
|
|
|
requests for IPv6 addresses.
|