21 个版本

0.3.1 2024 年 7 月 24 日
0.3.0 2024 年 7 月 20 日
0.2.24 2024 年 7 月 16 日
0.2.23 2024 年 6 月 23 日
0.2.11 2024 年 2 月 25 日

#301网络编程

Download history 167/week @ 2024-04-26 127/week @ 2024-05-03 38/week @ 2024-05-10 9/week @ 2024-05-17 168/week @ 2024-05-24 23/week @ 2024-05-31 6/week @ 2024-06-07 150/week @ 2024-06-14 148/week @ 2024-06-21 8/week @ 2024-06-28 121/week @ 2024-07-12 257/week @ 2024-07-19 43/week @ 2024-07-26 6/week @ 2024-08-02

312 每月下载量

MITGPL-3.0-or-later

145KB
3K SLoC

Rust 3K SLoC // 0.0% comments Shell 321 SLoC // 0.1% comments Bitbake 20 SLoC

tun2proxy

Linux、Android、macOS、iOS 和 Windows 上 HTTP 和 SOCKS 代理的隧道接口。

Crates.io tun2proxy Documentation Download License

更多信息可以在 wiki 中找到

特性

  • HTTP 代理支持(未认证、基本和摘要认证)
  • SOCKS4 和 SOCKS5 支持(未认证、用户名/密码认证)
  • SOCKS4a 和 SOCKS5h 支持(通过虚拟 DNS 功能)
  • 为所有流量设置最小的配置
  • 支持 IPv4 和 IPv6
  • 针对某些用例的 GFW 避免机制(见 问题 #35
  • SOCKS5 UDP 支持
  • 本地支持代理 DNS over TCP

构建

克隆存储库并将 cd 进入项目文件夹。然后运行以下命令

cargo build --release

构建适用于 Apple 设备的框架

要为 macOS 和 iOS 构建一个 XCFramework,请运行以下命令

./build-apple.sh

安装

从二进制文件安装

发布 下载二进制文件并将其放在您的 PATH 中。

真实性验证

从 v0.2.23 开始支持 构建起源证明。这些证明允许您确保构建是通过 GitHub CI/CD 流程从 GitHub 上的代码生成的。要验证构建文件的真实性,您可以使用 GitHub CLI

gh attestation verify <*.zip file> --owner tun2proxy

从源安装

如果您已安装 rust 工具链,则此操作应该会成功

cargo install tun2proxy

注意:在 Windows 上,您需要将 wintun DLL 复制到与二进制文件相同的目录。默认情况下,它是 %USERPROFILE%\.cargo\bin

设置

自动设置

使用--setup,可以让tun2proxy配置您的系统,自动将所有流量通过指定的代理路由。这需要以root权限运行工具,并将大致执行描述手动设置的章节中概述的步骤,但使用挂载绑定来覆盖/etc/resolv.conf文件。

您可以使用以下命令运行工具

sudo ./target/release/tun2proxy --setup --proxy "socks5://1.2.3.4:1080"

除了SOCKS5外,还支持SOCKS4和HTTP。

请注意,如果您的代理是一个非全局IP地址(例如,因为代理是由运行在本地的某些隧道工具提供的),您还需要提供通过实际隧道传输流量的服务器的公网IP地址。在这种情况下,如果您想使用自动设置功能,工具将告诉您通过--bypass <IP/CIDR>指定地址。

手动设置

一个标准的设置,可以将系统中的所有流量通过隧道接口路由,可能如下所示

# The proxy type can be either SOCKS4, SOCKS5 or HTTP.
PROXY_TYPE=SOCKS5
PROXY_IP=1.2.3.4
PROXY_PORT=1080
BYPASS_IP=123.45.67.89

# Create a tunnel interface named tun0 which you can bind to,
# so we don't need to run tun2proxy as root.
sudo ip tuntap add name tun0 mode tun
sudo ip link set tun0 up

# To prevent a routing loop, we add a route to the proxy server that behaves
# like the default route.
sudo ip route add "$BYPASS_IP" $(ip route | grep '^default' | cut -d ' ' -f 2-)

# Route all your traffic through tun0 without interfering with the default route.
sudo ip route add 128.0.0.0/1 dev tun0
sudo ip route add 0.0.0.0/1 dev tun0

# 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

# Make sure that DNS queries are routed through the tunnel.
sudo sh -c "echo nameserver 198.18.0.1 > /etc/resolv.conf"

./target/release/tun2proxy --tun tun0 --proxy "$PROXY_TYPE://$PROXY_IP:$PROXY_PORT"

此工具实现了一个虚拟DNS功能,由--dns virtual开关使用。当检测到端口53的DNS数据包时,从198.18.0.0/15选择一个IP地址并将其映射到查询名称。旨在该范围内的IP地址的连接将向代理提供映射后的查询名称而不是IP地址。由于许多代理不支持UDP,这通常可以使大多数情况下的即插即用体验成为可能,而不需要依赖第三方解析器或应用程序。根据您的用例,您可能想使用--dns direct禁用此功能。在这种情况下,您可能需要一个额外的工具,如dnsproxy,该工具配置为监听本地UDP端口,并通过TCP与第三方上游DNS服务器通信。

当您终止此程序并想消除上述几个命令造成的影响时,可以执行以下命令。路由将与隧道设备一起自动删除。

sudo ip link del tun0

CLI

Tunnel interface to proxy.

Usage: tun2proxy [OPTIONS] --proxy <URL> [ADMIN_COMMAND]...

Arguments:
  [ADMIN_COMMAND]...  Specify a command to run with root-like capabilities in the new namespace when using `--unshare`.
                      This could be useful to start additional daemons, e.g. `openvpn` instance

Options:
  -p, --proxy <URL>            Proxy URL in the form proto://[username[:password]@]host:port, where proto is one of
                               socks4, socks5, http. For example: socks5://myname:[email protected]:1080
  -t, --tun <name>             Name of the tun interface, such as tun0, utun4, etc. If this option is not provided, the
                               OS will generate a random one
      --tun-fd <fd>            File descriptor of the tun interface
      --unshare                Create a tun interface in a newly created unprivileged namespace while maintaining proxy
                               connectivity via the global network namespace
  -6, --ipv6-enabled           IPv6 enabled
  -s, --setup                  Routing and system setup, which decides whether to setup the routing and system
                               configuration. This option is only available on Linux and requires root-like privileges.
                               See `capabilities(7)`
  -d, --dns <strategy>         DNS handling strategy [default: direct] [possible values: virtual, over-tcp, direct]
      --dns-addr <IP>          DNS resolver address [default: 8.8.8.8]
  -b, --bypass <IP/CIDR>       IPs used in routing setup which should bypass the tunnel, in the form of IP or IP/CIDR.
                               Multiple IPs can be specified, e.g. --bypass 3.4.5.0/24 --bypass 5.6.7.8
      --tcp-timeout <seconds>  TCP timeout in seconds [default: 600]
      --udp-timeout <seconds>  UDP timeout in seconds [default: 10]
  -v, --verbosity <level>      Verbosity level [default: info] [possible values: off, error, warn, info, debug, trace]
  -h, --help                   Print help
  -V, --version                Print version

目前,tun2proxy支持HTTP、SOCKS4/SOCKS4a和SOCKS5。代理以URL格式提供给--proxy参数。例如,一个位于1.2.3.4:3128的HTTP代理,用户名为john.doe,密码为secret,提供为--proxy http://john.doe:secret@1.2.3.4:3128。这类似于curl的--proxy参数。

Docker支持

Tun2proxy可以作为其他Docker容器的代理。要使用此功能,首先构建镜像

docker build -t tun2proxy .

然后,从tun2proxy镜像启动一个容器

docker run -d \
	-v /dev/net/tun:/dev/net/tun \
	--sysctl net.ipv6.conf.default.disable_ipv6=0 \
	--cap-add NET_ADMIN \
	--name tun2proxy \
	tun2proxy --proxy proto://[username[:password]@]host:port

然后,您可以通过共享网络命名空间(如kubernetes sidecar)将运行中的容器的网络提供给另一个工作容器

docker run -it \
	--network "container:tun2proxy" \
	ubuntu:latest

配置技巧

DNS

当您的机器上的服务或本地网络中的服务器执行DNS解析时,DNS解析将通过隧道接口进行,因为指向localhost或您的本地网络的路径比0.0.0.0/1128.0.0.0/1更具体。在这种情况下,建议您更新/etc/resolv.conf文件以使用通过隧道接口路由的名称服务器地址。当虚拟DNS正常工作时,您将看到类似DNS查询example.org的日志消息,这是您的机器解析后连接到的主机名。

请注意,像NetworkManager这样的软件可能会在任何时候自动更改/etc/resolv.conf文件,从而导致DNS泄露。一种防止这种情况的临时解决方案是将文件设置为不可变,如下所示:sudo chattr +i "$(realpath /etc/resolv.conf)"

IPv6

一些代理服务器可能不支持IPv6。在虚拟DNS中使用时,这不是问题,因为DNS名称由代理服务器解析。当DNS名称在本地解析为IPv6地址时,这成为问题,因为代理将要求与IPv6目的地建立连接。在这种情况下,您可以在机器上禁用IPv6。这可以通过sysctl -w net.ipv6.conf.all.disable_ipv6=1sysctl -w net.ipv6.conf.default.disable_ipv6=1或通过ip -6 route del default来完成,这将导致libc解析器(和其他软件)不发出针对IPv6地址的DNS AAAA请求。

依赖关系

~21–35MB
~574K SLoC