如何为不同程序指定ppp0、ppp1双网络接口路由?
当然有可行方案!我来给你梳理几个实用的办法,解决不同程序绑定不同PPP接口的问题:
方案1:策略路由(系统级控制,无需修改程序)
这是最常用的方案,通过创建自定义路由表和匹配规则,让特定流量走指定接口,完美解决你只有一条默认路由的问题。
操作步骤:
添加自定义路由表
先给两个PPP接口各创建一个专属路由表,编辑路由表配置文件:echo "100 ppp0table" >> /etc/iproute2/rt_tables echo "101 ppp1table" >> /etc/iproute2/rt_tables这里
100、101是路由表的ID(只要不冲突就行),ppp0table是表名,方便识别。给路由表添加默认路由
分别给两个路由表配置对应接口的默认路由:ip route add default dev ppp0 table ppp0table ip route add default dev ppp1 table ppp1table这样,匹配到
ppp0table的流量就会走ppp0接口,同理ppp1。添加流量匹配规则
你可以按用户UID或者进程ID来指定哪些流量用哪个路由表,举两个常用场景:- 让某个用户的所有程序走ppp0:
# 假设目标用户的UID是1000,替换成你的实际UID ip rule add uidrange 1000-1000 lookup ppp0table - 让特定进程走ppp1(需要先获取进程PID):
# 假设PID是1234,替换成你的目标进程PID ip rule add pid 1234 lookup ppp1table
- 让某个用户的所有程序走ppp0:
验证效果
切换到目标用户或者直接运行进程,用curl --interface ppp0 ifconfig.me(或者查看进程的网络连接),就能看到流量确实走了指定接口。
方案2:网络命名空间(彻底隔离不同接口的网络环境)
如果需要完全隔离两个接口的网络环境(比如不同的DNS、防火墙规则),网络命名空间是最佳选择,每个命名空间有独立的路由表和网络配置。
操作步骤:
创建网络命名空间
ip netns add ns-ppp0 ip netns add ns-ppp1将PPP接口移到对应命名空间
# 把ppp0移到ns-ppp0命名空间 ip link set ppp0 netns ns-ppp0 # 把ppp1移到ns-ppp1命名空间 ip link set ppp1 netns ns-ppp1配置命名空间内的网络
分别进入每个命名空间,配置IP和默认路由:# 配置ns-ppp0 ip netns exec ns-ppp0 ip addr add $(ip netns exec ns-ppp0 ip addr show ppp0 | grep inet | awk '{print $2}') dev ppp0 ip netns exec ns-ppp0 ip route add default dev ppp0 # 配置ns-ppp1 ip netns exec ns-ppp1 ip addr add $(ip netns exec ns-ppp1 ip addr show ppp1 | grep inet | awk '{print $2}') dev ppp1 ip netns exec ns-ppp1 ip route add default dev ppp1在命名空间内运行程序
# 让程序走ppp0 ip netns exec ns-ppp0 your-program # 让程序走ppp1 ip netns exec ns-ppp1 your-program
方案3:代理转发(程序级灵活指定)
如果只是临时给个别程序指定接口,代理方案更灵活,不需要修改系统路由。核心思路是在指定接口上启动本地代理,让程序通过代理转发流量。
操作步骤:
在指定接口上启动SOCKS5代理
可以用sshd快速搭建临时代理,或者用专业的dante-server:# 用sshd在ppp0接口的IP上启动SOCKS5代理(端口1080) sshd -D -p 1080 -o "GatewayPorts no" -o "ListenAddress $(ip addr show ppp0 | grep inet | awk '{print $2}' | cut -d/ -f1)"同理,给ppp1也启动一个代理(比如端口1081)。
用Proxychains让程序走代理
安装proxychains-ng后,编辑配置文件/etc/proxychains.conf,添加代理地址:[ProxyList] socks5 <ppp0的IP> 1080然后运行程序:
proxychains4 your-program
为什么你之前的curl --interface没用?
因为虽然你指定了出口接口,但系统没有给该接口配置回包路由——数据包发出去后,对方的回包找不到回来的路径,所以只有默认路由的接口能正常工作。上面的方案要么给接口补全了路由(策略路由、网络命名空间),要么通过代理确保流量往返都走指定接口。
内容的提问来源于stack exchange,提问作者Cassini

