Linux 机器上有多个网卡,想要让其中的一个程序使用 eth1 而不是默认的 网卡,不影响其他程序。
大概思路是这样的:
1. 设置一个路由规则,将带了 0x100 mark 的流量通过 table 123 查找路由:
ip rule add fwmark 0x100 table 123;
2. table 123 中下发一条 默认路由 路由规则,就是通过 eth1 出去:
ip route add default dev eth1 table 123 scope global pref 123
3. 然后给特定程序打标签。
但是怎么给特定程序打标签或者说打mark呢,这里有多中办法。如果能够确定程序的端口,直接通过iptables对特定端口打mark也是可以的,这里介绍一下更加通用的方法。
方法1:在应用程序中 通过SO_MARK给程序所有往外发的报文打上mark
mark = 0x100;
setsockopt(client_socket,SOL_SOCKET,SO_MARK,&ma rk,sizeof(mark) );
但是这种方法是改动代码
方法2:通过 iptables owner 模块 只要给进程分配一个单独的 user 来运行就好了。
owner match options:
[!] --uid-owner userid[-userid] Match local UID
[!] --gid-owner groupid[-groupid] Match local GID
[!] --socket-exists Match if socket exists
[root@0000dede-vmxg3eslgl bin]# iptables -m owner --help
iptables -t mangle -A OUTPUT -m owner --uid-owner user-xxx -j MARK --set-mark 0x100
方法3:通过 iptables cgroup 模块
cd /sys/fs/cgroup/net_cls
mkdir progxxx 创建一个文件夹
[root@localhost progxxx]# ll 默认就有这么多文件
total 0
-rw-r--r-- 1 root root 0 Jul 7 11:03 cgroup.clone_children
--w--w--w- 1 root root 0 Jul 7 11:03 cgroup.event_control
-rw-r--r-- 1 root root 0 Jul 7 11:04 cgroup.procs
-rw-r--r-- 1 root root 0 Jul 7 11:04 net_cls.classid
-rw-r--r-- 1 root root 0 Jul 7 11:03 net_prio.ifpriomap
-r--r--r-- 1 root root 0 Jul 7 11:03 net_prio.prioidx
-rw-r--r-- 1 root root 0 Jul 7 11:03 notify_on_release
-rw-r--r-- 1 root root 0 Jul 7 11:03 tasks
查找进程的pid,这里假设pid为15445
echo 15445 > cgroup.procs
设置一个classid 这里假设0x12345
echo 0x12345 > net_cls.classid
iptables -t mangle -I OUTPUT -m cgroup --cgroup 0x12345 -j MARK --set-mark 0x100