Linux如何限制程序使用哪块网卡?

现在有一个两块网卡的电脑,我想让一个程序使用有线网卡访问网络,但是他一直通过无线网卡连接,用什么办法可以做到不让这个程序使用指定的网卡?

使用的发行版是ubuntu,两块网卡都是可以访问外网的,而且确实需要两块网卡都访问外网,所以不能简单的禁用某一块网卡。

eth0      Link encap:以太网  硬件地址 ac:16:2d:0b:0f:7b  
          inet6 地址: 2001:250:1006:5090:ae16:2dff:fe0b:f7b/64 Scope:Global
          inet6 地址: fe80::ae16:2dff:fe0b:f7b/64 Scope:Link
          inet6 地址: 2001:250:1006:5090:5125:3dce:2e39:3435/64 Scope:Global
          inet6 地址: 2001:250:1006:5090:3986:8f63:3bc4:ed62/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:689138 错误:5 丢弃:96 过载:0 帧数:3
          发送数据包:70167 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000 
          接收字节:96407419 (96.4 MB)  发送字节:12030321 (12.0 MB)
          中断:20 Memory:fb100000-fb120000 

eth0:avahi Link encap:以太网  硬件地址 ac:16:2d:0b:0f:7b  
          inet 地址:169.254.4.53  广播:169.254.255.255  掩码:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          中断:20 Memory:fb100000-fb120000 

lo        Link encap:本地环回  
          inet 地址:127.0.0.1  掩码:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  跃点数:1
          接收数据包:18101 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:18101 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0 
          接收字节:1755000 (1.7 MB)  发送字节:1755000 (1.7 MB)

virbr0    Link encap:以太网  硬件地址 26:cd:4d:24:53:90  
          inet 地址:192.168.122.1  广播:192.168.122.255  掩码:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  跃点数:1
          接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0 
          接收字节:0 (0.0 B)  发送字节:0 (0.0 B)

wlan0     Link encap:以太网  硬件地址 00:1d:0f:31:49:9c  
          inet 地址:192.168.1.102  广播:192.168.1.255  掩码:255.255.255.0
          inet6 地址: fe80::21d:fff:fe31:499c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:544819 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:305276 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000 
          接收字节:481549142 (481.5 MB)  发送字节:54082231 (54.0 MB)
阅读 20.3k
5 个回答

这个程序用 TCP/IP 协议和外部通信时, 用哪个网卡, 服务端的话是由 bind() 的参数决定的. 你可以把套接字绑定到你指定的 ip 地址和端口上. 如果你的 IP 地址指定的是 htonl(INADDR_ANY), 就由内核去选择 IP 地址. 如果你有这个程序的源码的话, 你可以通过自己指定套接字绑定的 IP 地址来实现你的需求. 如果是客户端, connect() 前一般不调用 bind(), 由内核确定使用哪块网卡. 内核如何选择网卡, 是由你的程序连接的目的地址和路由表决定的. linux 下, 你可以通过 route 等工具配置哪些地址段使用哪个网卡, 这并不是为一个程序所指定的, 而是对每一个连接都生效的. 具体你可以搜索下多网卡的路由配置方法.

除了利用 LD_PRELOAD 来 hack 程序外,我能想到的另一个方案是,建立一个新的网络名字空间(参见unshare(2)),在那个名字空间里建立一块虚拟网卡来进行网络通信。然后,利用 iptables 将所有来自那个虚拟网卡的流量重定向到你指定的网卡上。

理论上可行,但是我也不知道虚拟网卡那块怎么搞……

五年后的更新:用 ip link 命令加一对 veth 虚拟网卡,然后就可以用 iptables / ip rule / ip route 之类的把流量弄过去了。具体细节我就不研究了。

通常情况,非特殊程序联网,不会指定使用有线还是无线网卡,更不会指定用哪个网卡。假如同时有两块网卡(笔记本就有无线有无线两块),在有线和无线都连上的情况下,使用哪个网线上网,是系统决定的,如果用户自己没对此时行特别设置的话,系统会默认使用有线的。如果你正在使用有图形界面的Linux,在托盘的网络图标就可以设置,把无线网卡禁掉。如果非图形界面,你要告诉大家你是用什么发行版的Linux,假设你两个网卡都可以联网了,那就试下在终端打入以下命令来禁无线网卡: ifconfig wlan0 down 如果执行完后,程序无法联网,就说明你的有线网卡没配置好,你要给大家提供更多的信息,比如可以打入: ifconfig -a 把输出粘上来给大家看。

通过iptable 根据 源和目的IP,让指定的流量从指定网卡出去

新手上路,请多包涵

讓你的某個應用程式能從指定的網卡上網
环境设定

wlan0:
ip 192.168.0.101
netmask 255.255.255.0
gateway 192.168.0.1

veth0: (bridge 或 nat 介面)
ip 10.1.2.254
netmask 255.255.255.0

veth1: (network namespace myns 中的網卡)
ip 10.1.2.1
netmask 255.255.255.0
gateway 10.1.2.254
# 1. 建立一个 network namespace
sudo ip netns add myns

# 2. 建立两张虚拟网卡 (veth0、veth1)
sudo ip link add veth0 type veth peer name veth1
sudo ip link set veth1 netns myns  # 把veth1移动到myns namespace中

# 3. 设置 NAT mode
sudo ip addr add 10.1.2.254/24 dev veth0
sudo ip link set veth0 up

sudo ip netns exec myns ip link set lo up
sudo ip netns exec myns ip link set veth1 up
sudo ip netns exec myns ip addr add 10.1.2.1/24 dev veth1

sudo ip netns exec myns ip route add default via 10.1.2.254
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -I POSTROUTING -s 10.1.2.1 -o wlan0 -j MASQUERADE

# 4. 设置 policy routing
sudo vim /etc/iproute2/rt_tables
200 from_wifi

sudo ip route add default via 192.168.0.1 dev wlan0 table from_wifi
ip route show table from_wifi
sudo ip rule add from 10.1.2.1 dev veth0 table from_wifi
sudo ip rule add to 10.1.2.1 dev veth0 table from_wifi

# 5. 测试
sudo ip netns exec myns curl https://ip.cn
curl https://ip.cn
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏