一台机器两块网卡,每块接一根网线,两根网线是两家不同的运营商的,系统准备装 debian 或 fedora,请问如何指定某个程序走某根网线??

2016-11-28 09:44:32 +08:00
 qceytzn

如何设置呢?哪个命令可以区分开 eth0 和 eth1 ?

3928 次点击
所在节点    Linux
23 条回复
sagaxu
2016-11-28 09:50:02 +08:00
用容器比较容易实现
gamexg
2016-11-28 09:58:33 +08:00
下面是通过绑定本地 ip 实现线路切换,不过也可以设置为通过用户 id 之类的分配线路。那种需要用 iptables 打标签来做。


计划使用的策略师程序绑定不同的本地地址就走不同的路由表走。

root@ubuntu-1u:/home/gamexg# echo 300 tel >>/etc/iproute2/rt_tables
root@ubuntu-1u:/home/gamexg# echo 400 cmcc >>/etc/iproute2/rt_tables
root@ubuntu-1u:/home/gamexg# ip route add default via 192.168.101.1 table cmcc
root@ubuntu-1u:/home/gamexg# ip route add default via 192.168.87.1 table tel
root@ubuntu-1u:/home/gamexg# ip rule add from 192.168.87.88/32 table tel pref 300
root@ubuntu-1u:/home/gamexg# ip rule add from 192.168.101.88/32 table cmcc pref 400

上面操作后会出现一个问题,局域网连接不上啦,因为本机的全部转发给了网关…
解决办法,修改 cmcc 、 tel 路由表加上本地网络或者添加策略路由规则,局域网的走默认路由。(见结尾)

root@ubuntu-1u:/home/gamexg# ./d
HTTP/1.1 200 OK
Server: Cowboy
Connection: close
Content-Type: text/plain
Date: Mon, 26 Sep 2016 10:13:35 GMT
Content-Length: 14
Via: 1.1 vegur

*******
root@ubuntu-1u:/home/gamexg# ./d -sip 192.168.87.88
HTTP/1.1 200 OK
Server: Cowboy
Connection: close
Content-Type: text/plain
Date: Mon, 26 Sep 2016 10:13:57 GMT
Content-Length: 13
Via: 1.1 vegur

******
root@ubuntu-1u:/home/gamexg# ./d -sip 192.168.101.88
HTTP/1.1 200 OK
Server: Cowboy
Connection: close
Content-Type: text/plain
Date: Mon, 26 Sep 2016 10:14:16 GMT
Content-Length: 14
Via: 1.1 vegur

******

可以看到已经可以通过指定本地地址的方式指定出口了。

# 显示当前策略路由
root@ubuntu-1u:/home/gamexg# ip rule list
0: from all lookup local
300: from 192.168.87.88 lookup tel
400: from 192.168.101.88 lookup cmcc
32766: from all lookup main
32767: from all lookup default

# 显示默认路由表(main)
root@ubuntu-1u:/home/gamexg# ip route list
default via 192.168.101.1 dev enp2s0 onlink
default via 192.168.87.1 dev enx00e04c5200a2 metric 30 onlink
10.10.10.0/24 dev zt0 proto kernel scope link src 10.10.10.2
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.87.0/24 dev enx00e04c5200a2 proto kernel scope link src 192.168.87.88
192.168.101.0/24 dev enp2s0 proto kernel scope link src 192.168.101.88

# 显示指定路由表 main
root@ubuntu-1u:/home/gamexg# ip route list table main
default via 192.168.101.1 dev enp2s0 onlink
default via 192.168.87.1 dev enx00e04c5200a2 metric 30 onlink
10.10.10.0/24 dev zt0 proto kernel scope link src 10.10.10.2
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.87.0/24 dev enx00e04c5200a2 proto kernel scope link src 192.168.87.88
192.168.101.0/24 dev enp2s0 proto kernel scope link src 192.168.101.88

# 显示制定路由表 local
root@ubuntu-1u:/home/gamexg# ip route list table local
broadcast 10.10.10.0 dev zt0 proto kernel scope link src 10.10.10.2
local 10.10.10.2 dev zt0 proto kernel scope host src 10.10.10.2
broadcast 10.10.10.255 dev zt0 proto kernel scope link src 10.10.10.2
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 172.17.0.0 dev docker0 proto kernel scope link src 172.17.0.1
local 172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1
broadcast 172.17.255.255 dev docker0 proto kernel scope link src 172.17.0.1
broadcast 192.168.87.0 dev enx00e04c5200a2 proto kernel scope link src 192.168.87.88
local 192.168.87.88 dev enx00e04c5200a2 proto kernel scope host src 192.168.87.88
broadcast 192.168.87.255 dev enx00e04c5200a2 proto kernel scope link src 192.168.87.88
broadcast 192.168.101.0 dev enp2s0 proto kernel scope link src 192.168.101.88
local 192.168.101.88 dev enp2s0 proto kernel scope host src 192.168.101.88
broadcast 192.168.101.255 dev enp2s0 proto kernel scope link src 192.168uu 锁.101.88

# 修复之前策略路由造成本地无法访问的问题
root@ubuntu-1u:/home/gamexg# ip rule add to 192.168.101.0/24 table main
oot@ubuntu-1u:/home/gamexg# ip rule add to 192.168.87.0/24 table main=
gamexg@ubuntu-1u:~$ ip rule
0: from all lookup local
298: from all to 192.168.87.0/24 lookup main
299: from all to 192.168.101.0/24 lookup main
300: from 192.168.87.88 lookup tel
400: from 192.168.101.88 lookup cmcc
32766: from all lookup main
32767: from all lookup default
fangdingjun
2016-11-28 10:04:57 +08:00
用 iptables mark 加 iproute2 策略路由 可以实现


大致的命令如下

echo 200 ppp0 >> /etc/iproute2/rt_tables
echo 201 ppp1 >> /etc/iproute2/rt_tables

ip route add default dev ppp0 table ppp0
ip route add default dev ppp1 table ppp1

iptables -t mangle -A PREROUTING -o lo -j ACCEPT
iptables -t mangle -A PREROUTING -m uid --uid 1001 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -m uid --uid 1002 -j MARK --set-mark 11

ip rule add fwmark 10 lookup ppp0
ip rule add fwmark 11 lookup ppp1
defunct9
2016-11-28 10:39:52 +08:00
是某个程序,需要具体情况具体分析。
royceyong
2016-11-28 10:42:32 +08:00
由特征决定方法
ceyes
2016-11-28 10:55:55 +08:00
为何有这需求呢?
不如把 eth0 eth1 作成 bonding 好了 😄
crazycen
2016-11-28 11:46:11 +08:00
这不是路由器的功能么!
auser
2016-11-28 11:52:12 +08:00
如果是自己写程序的话,通常 bind(2)就行了。

根据程序的话:最好用 namespace 特性来设置环境(两块虚拟网卡)和启动程序,然后在主空间设置策略路由。
如果楼主知道其中的知识,不想摸索的话,我可以再详细说下方法。
salmon5
2016-11-28 12:05:31 +08:00
根据访问调用 IP ,改路由表。
KCheshireCat
2016-11-28 13:35:35 +08:00
不同程序使用不同用户来运行

iptables 上面使用 owner 模块匹配不同用户的数据包,然后对数据包打上 MARK 标记

ip rule 里面对不同标记走不同路路由表

ip route 在对应路由表设置默认路由

OK 完事儿
raysonx
2016-11-28 14:22:39 +08:00
首先,程序可以把 socket bind 到某个特定的 interface ,之后所有的数据都会从那个 interface 发出,这个优先级是最高的。
其次,如果
raysonx
2016-11-28 14:24:56 +08:00
程序没有绑定某一张网卡或者源 IP 地址,就会通过查找路由表来确定走哪张网卡。
luxinxin
2016-11-28 14:52:32 +08:00
周末解决了类似的问题,用的是 @fangdingjun @KCheshireCat 的思路。
luxinxin
2016-11-28 14:56:27 +08:00
补充一点,由于是两家运营商的,所以你可能在 DNS 上掉坑(我周末调试了一天就是因为这个)。切记要防止 A 线路的请求跑到 B 线路的 DNS 上去!
YingJie
2016-11-28 16:50:39 +08:00
还真是什么需求都有·····
KCheshireCat
2016-11-28 17:03:28 +08:00
@raysonx 仔细想了一下本地路由流程,我觉得他方法才是对的,本地程序是先经过路由表选择才再走 iptables 的,需要程序自己绑定接口才能走对应出口

我脑子抽了一下

你需要自己写个转发包的小程序,或者修改原本的程序

或者直接在 ip rule 上用目标地址条件选择路由表
raysonx
2016-11-28 17:52:00 +08:00
@KCheshireCat 并不是.类似 PREROUTING 链是在路由选择之前触发的。
KCheshireCat
2016-11-28 18:01:15 +08:00
@raysonx 是,但是看 lz 的需求应该是指本地发出的连接,从发出这条线来看所有表都在路由选择之后

如果 lz 是有两台本地机器的话,那就可以用 PREROUTING 链来处理了
28ms
2016-11-28 18:40:32 +08:00
iptables ipset dnsmasq 走路由表策略,网上大把这样的教程
qceytzn
2016-11-29 02:16:40 +08:00
@sagaxu docker 有个问题就是音频和视频要另外设置,看着有点烦~~~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/323744

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX