使用Clash在Debian系统上用TProxy模式搭建透明代理

透明代理是一种网络代理,其目的是在用户和网络之间提供透明连接,使用户的网络请求被代理服务器处理,而用户不知道网络连接正在被代理。与其他类型的代理不同,透明代理不需要任何额外的配置或配置,因为它们通过简单地将用户的请求发往代理服务器来自动工作。本文将介绍在Debian系统上,使用Clash(Premium版)来搭建透明代理的过程。

TProxy是一种Linux内核网络协议栈中的一种透明代理技术。它可以使得Linux操作系统中的应用程序在发送数据包时,数据包能够通过内核的TProxy模块,从而被重定向到TProxy监听的端口上,然后进行一些透明代理的处理,然后再由TProxy代理继续转发数据包。TProxy的优点是可以实现真正的透明代理,不用更改客户端的网络设置即可使用代理服务,支持layer 4负载平衡和层七协议转发等功能,同时可以提高代理性能,更易于集群化部署。TProxy同时支持TCP和UDP。

安装Clash Premium

首先在https://github.com/Dreamacro/clash/releases/tag/premium下载最新版的clash premium版,然后上传到debian中,将其放在/usr/local/bin/clash,配置文件放在/usr/local/etc/clash文件夹中。配置文件中与透明代理部分相关内容如下:

port: 7890
socks-port: 7891
#redir-port: 7892
#mixed-port: 7893
tproxy-port: 7896
allow-lan: true
bind-address: '*'
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
secret: ''

profile:
  store-selected: true
  store-fake-ip: true

dns:
  enable: true
  listen: '0.0.0.0:53'
  default-nameserver:
    - 223.5.5.5
    - 119.29.29.29
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    # 以下域名列表参考自 vernesong/OpenClash 项目,并由 Hackl0us 整理补充
    # === LAN ===
    - '*.lan'
    # === Linksys Wireless Router ===
    - '*.linksys.com'
    - '*.linksyssmartwifi.com'
    # === Apple Software Update Service ===
    - 'swscan.apple.com'
    - 'mesu.apple.com'
    # === Windows 10 Connnect Detection ===
    - '*.msftconnecttest.com'
    - '*.msftncsi.com'
    # === NTP Service ===
    - 'time.*.com'
    - 'time.*.gov'
    - 'time.*.edu.cn'
    - 'time.*.apple.com'

    - 'time1.*.com'
    - 'time2.*.com'
    - 'time3.*.com'
    - 'time4.*.com'
    - 'time5.*.com'
    - 'time6.*.com'
    - 'time7.*.com'

    - 'ntp.*.com'
    - 'ntp.*.com'
    - 'ntp1.*.com'
    - 'ntp2.*.com'
    - 'ntp3.*.com'
    - 'ntp4.*.com'
    - 'ntp5.*.com'
    - 'ntp6.*.com'
    - 'ntp7.*.com'

    - '*.time.edu.cn'
    - '*.ntp.org.cn'
    - '+.pool.ntp.org'

    - 'time1.cloud.tencent.com'
    # === Music Service ===
    ## NetEase
    - '+.music.163.com'
    - '*.126.net'
    ## Baidu
    - 'musicapi.taihe.com'
    - 'music.taihe.com'
    ## Kugou
    - 'songsearch.kugou.com'
    - 'trackercdn.kugou.com'
    ## Kuwo
    - '*.kuwo.cn'
    ## JOOX
    - 'api-jooxtt.sanook.com'
    - 'api.joox.com'
    - 'joox.com'
    ## QQ
    - '+.y.qq.com'
    - '+.music.tc.qq.com'
    - 'aqqmusic.tc.qq.com'
    - '+.stream.qqmusic.qq.com'
    ## Xiami
    - '*.xiami.com'
    ## Migu
    - '+.music.migu.cn'
    # === Game Service ===
    ## Nintendo Switch
    - '+.srv.nintendo.net'
    ## Sony PlayStation
    - '+.stun.playstation.net'
    ## Microsoft Xbox
    - 'xbox.*.microsoft.com'
    - '+.xboxlive.com'
    - '+.xboxlive.cn'
    # === Other ===
    ## QQ Quick Login
    - 'localhost.ptlogin2.qq.com'
    ## Golang
    - 'proxy.golang.org'
    ## STUN Server
    - 'stun.*.*'
    - 'stun.*.*.*'


    ## Bilibili CDN
    - '*.mcdn.bilivideo.cn'

    ## CMCC
    - "*.cmpassport.com"
    - "*.jegotrip.com.cn"

  nameserver:
    - 223.5.5.5
    - 119.29.29.29
# fallback:
#   - tls://1.1.1.1:853
#   - tcp://1.1.1.1:53
#   - tcp://208.67.222.222:443
#   - tls://dns.google
  nameserver-policy:
    '+.msftconnecttest.com': '114.114.114.114'
    '+.msftncsi.com': '114.114.114.114'

然后新建/etc/systemd/system/clash.service,内容如下:

[Unit]
Description=Clash daemon, A rule-based proxy in Go.
After=network.target

[Service]
Type=simple
Restart=always
ExecStart=/usr/local/bin/clash -d /usr/local/etc/clash

[Install]
WantedBy=multi-user.target

执行systemctl enable --now clash,启用并且启动Clash服务。此时Clash已经成功作为服务运行,但是服务器转发的数据还不会被发送到Clash处理。

配置nftables和路由

编辑/etc/nftables.conf,在底下添加以下内容,注意不要把nftables.conf中原来的内容替换掉。

table inet clash {
	set local_ipv4 {
		type ipv4_addr
		flags interval
		elements = {
			10.0.0.0/8,
			127.0.0.0/8,
			169.254.0.0/16,
			172.16.0.0/12,
			192.168.0.0/16,
			240.0.0.0/4
		}
	}

	set local_ipv6 {
		type ipv6_addr
		flags interval
		elements = {
			::ffff:0.0.0.0/96,
			64:ff9b::/96,
			100::/64,
			2001::/32,
			2001:10::/28,
			2001:20::/28,
			2001:db8::/32,
			2002::/16,
			fc00::/7,
			fe80::/10
		}
	}

	chain clash-tproxy {
		fib daddr type { unspec, local, anycast, multicast } return
		ip daddr @local_ipv4 return
		ip6 daddr @local_ipv6 return
		udp dport { 123 } return
		meta l4proto { tcp, udp } meta mark set 1 tproxy to :7896 accept
	}

#	chain clash-mark {
#		fib daddr type { unspec, local, anycast, multicast } return
#		ip daddr @local_ipv4 return
#		ip6 daddr @local_ipv6 return
#		udp dport { 123 } return
#		meta mark set 1
#	}
#
#	chain mangle-output {
#		type route hook output priority mangle; policy accept;
#		meta l4proto { tcp, udp } skgid != 997 ct direction original jump clash-mark
#	}

	chain mangle-prerouting {
		type filter hook prerouting priority mangle; policy accept;
		iifname { lo, ens3 } meta l4proto { tcp, udp } ct direction original jump clash-tproxy
	}
}

上面的配置只会透明代理服务器转发的流量,不会代理服务器自身产生的流量,如果要代理服务器自身产生的流量,可以参考被注释掉的部分,并让Clash服务以特定gid(示例中为997)运行。在Clash配置文件中,需要启用tproxy端口并设为7896。

配置修改完之后,执行systemctl enable --now nftables启用nftables服务。

编辑/etc/sysctl.conf文件,在最底部加入net.ipv4.ip_forward=1,然后执行sysctl -p,开启内核的转发功能。

最后需要添加相关的路由,新建/etc/systemd/system/clash-route.service,内容如下:

[Unit]
Description=Clash TProxy Rules
After=network.target
Wants=network.target

[Service]
User=root
Type=oneshot
RemainAfterExit=yes
# there must be spaces before and after semicolons
ExecStart=/sbin/ip rule add fwmark 1 table 100 ; /sbin/ip route add local default dev lo table 100 ; /sbin/ip -6 rule add fwmark 1 table 101 ; /sbin/ip -6 route add local ::/0 dev lo table 101
ExecStop=/sbin/ip rule del fwmark 1 table 100 ; /sbin/ip route del local default dev lo table 100 ; /sbin/ip -6 rule del fwmark 1 table 101 ; /sbin/ip -6 route del local ::/0 dev lo table 101

[Install]
WantedBy=multi-user.target

最后执行systemctl enable --now clash-route启用clash-route服务。这样透明代理就部署完成了。只需要将局域网中需要走代理的设备的网关和DNS均设置为Debian服务器的IP即可。