我正在尝试测试 Wi-Fi 网络,并且需要能够使用特定的网络适配器打开不同的 Chrome 或 Firefox 窗口(例如,我有两个 Wi-Fi 网络适配器 -wifi1
和wifi2
- 并且我想使用 打开一个 Google Chrome 窗口,使用wifi1
打开另一个窗口wifi2
)。
我检查过了iptables
但这不是我想要的。
欢迎任何想法。
答案1
具有网络命名空间的通用解决方案
有了网络命名空间,就可以实现这一点。您可以创建额外的网络命名空间,配置其网络设备,并最终在其中运行浏览器。
我假设您现在没有使用命名空间(ip netns
不打印任何内容)。
至少有两种方法可以使新添加的网络命名空间中的程序使用某个网络设备:
- 您可以将设备从默认网络命名空间(默认情况下它所属的位置)“移动”到可直接使用的添加命名空间。请参阅下面的示例 1。
- 如果您希望或需要设备停留在默认网络命名空间中(例如,它正在使用中;或者它已配置并且您不想再次配置它),您可以创建一个 veth 对,即两个虚拟接口:一个在默认网络命名空间中,另一个在添加的命名空间中。这可以像路由器和设备之间的电缆一样工作。您需要在添加的命名空间中正确配置 IP 地址和路由,并在默认命名空间中配置 NAT。请参阅下面的示例 2。
可能出现的问题
- 属于网络命名空间的网络设备不适用于在命名空间之外运行的程序。这意味着默认命名空间中的网络管理器(如果有)可能无法帮助您处理添加的命名空间中的设备,除非您(也)在那里运行它。为了进行测试,您可以在添加的命名空间中使用
ip
、等dhclient
,route
并(半)手动配置所有内容。 在添加的网络命名空间中 DNS 可能不可用。例如,在我的 Kubuntu 中,
/etc/resolv.conf
文件内容为:# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN # 127.0.0.53 is the systemd-resolved stub resolver. # run "systemd-resolve --status" to see details about the actual nameservers. nameserver 127.0.0.53
添加的命名空间有自己的
lo
设备,我可以将其调出。但这是一个不同于lo
存根解析器正在监听的默认网络命名空间的接口。最简单的测试解决方案是无论如何编辑文件并添加nameserver
指向计算机外部 DNS 服务器的条目;例如nameserver 8.8.8.8
或nameserver IP.of.your.router
。我在文件末尾添加了该条目。添加的命名空间中的进程无法使用127.0.0.53
,但它们将使用其他 DNS 服务器。如果您
resolv.conf
已经指定了可从添加的命名空间访问的服务器,那么就无需担心。如果您第二次运行浏览器,它可能会检测到已在运行的实例,将任务委托给它并退出。即使您在不同的网络命名空间中运行第二个实例,它也可能会将任务委托给旧实例。
我使用 Vivaldi,解决方案是指定非默认的
--user-data-dir
,因此不同浏览器的用户数据目录不同。例如:vivaldi --user-data-dir=/tmp/
我相信同样的方法也适用于 Chrome;但我不确定 Firefox 是否适用。最简单的解决方案可能是运行一次 Chrome 和一次 Firefox。
示例 1:直接使用设备
大多数命令都需要sudo
。为方便起见,您可以sudo su -
在提升的 shell 中运行和工作。
定义有用的变量。
dev
根据您的需要调整(设备名称)。netns=ns1 dev=wlp2s0
确保命名空间不存在。
ip netns del "$netns" 2>/dev/null
创建一个新的网络命名空间。
ip netns add "$netns"
将设备置于默认命名空间内(不是严格要求)。
ip link set dev "$dev" down
将其添加到新的命名空间(它将从默认命名空间中消失)。
这对于有线接口来说很好:
ip link set dev "$dev" netns "$netns"
对于无线接口,上述方法最有可能产生
Invalid argument
。然后这种方法:您需要移动 PHY
这会大概向您展示正确的 phy(期望
phy0
或类似):phy="$(basename "$(cd "/sys/class/net/$dev/phy80211" && pwd -P)")" echo "$phy"
实际命令:
iw phy "$phy" set netns name "$netns"
确认所有设备均位于其应在的位置。
ip link show ip netns exec "$netns" ip link show # examine output
启动接口。命名空间包含自己的环回设备
lo
。我也启动它,因为一般程序可能需要依赖它。ip netns exec "$netns" ip link set dev lo up ip netns exec "$netns" ip link set dev "$dev" up
请注意,最后这些命令是如何在正确的命名空间中
ip netns exec "$netns"
运行实际命令(ip link …
)的。我们每次都可以这样做。为方便起见,让我们在命名空间中运行一个全新的提升权限的 shell:# taking relevant variables to the new shell export netns dev phy # assuming the current shell is elevated # this will replace it with a new elevated shell in the namespace exec ip netns exec "$netns" su
您从这个新 shell 调用的所有内容都将在网络命名空间中运行。例如,sole
ip link show
应该会显示所需的设备,而不是属于默认命名空间的设备。在命名空间中配置接口。使用
iw
(如果是无线)、、ip
和route
/dhclient
或任何您通常需要的内容。无线接口的示例:wpa_passphrase mySSID myPass | wpa_supplicant -i "$dev" -c /dev/stdin -B dhclient "$dev"
注意 DNS(请参阅上面的“可能的问题”)。
在网络命名空间中运行单独的浏览器(请参阅上面的“可能的问题”)。您可能应该以普通用户身份运行它。示例:
# from the elevated shell in the network namespace sudo -u regularuser vivaldi --user-data-dir=/tmp/
示例 1 继续:恢复更改
到目前为止所做的更改都是临时的。如果出现任何问题,只需重新启动即可。
无需重启,您只需使用 即可删除网络命名空间ip netns del "$netns"
。当设备不再在已删除的命名空间中使用时,它将出现在默认命名空间中。您需要识别并终止正在使用它的进程(包括浏览器、shell 可能和wpa_supplicant
可能dhclient
)。参见:删除命名空间后缺少接口.有用的命令:
find /proc/ -name "$dev"
最好在删除附加设备之前明确将设备“返回”到默认命名空间。您可能dhclient
无论如何都想终止某些进程(如),否则它们将继续徒劳无功地运行。在“返回”设备之前找到它们并终止它们。但如果您错过了一些,在删除命名空间之前“返回”设备至少会使设备出现在默认命名空间中。您不会最终得到丢失的设备。
注意,默认网络命名空间没有名称,因此我使用属于它的某个进程的 PID。我敢打赌 init 进程属于默认网络命名空间,因此1
。
如果有线:
# from the elevated shell in our additional network namespace ip link set dev "$dev" netns 1
如果是无线的:
# from the elevated shell in our additional network namespace iw phy "$phy" set netns 1
然后删除命名空间:
ip netns del "$netns"
当设备出现在默认网络命名空间中时,您的网络管理器(如果有)可能会启动。或者您可以手动配置设备。
示例 2:veth 对
本示例基于网络命名空间作者 Diego Pino García和iptables - 将数据包路由到特定接口。我承认我对后者只有基本的了解,而且由于我必须对其进行调整,所以解决方案可能不是最佳的。
大多数命令都需要sudo
。为方便起见,您可以sudo su -
在提升的 shell 中运行和工作。
定义有用的变量。根据您的需要进行调整。
# arbitrary mark mark=11 netns="ns$mark" dev=wlp2s0 gate=192.168.80.1 # gate is the gateway dev connects to, like AP, home router or so # veth devices devdef="v-eth-$netns" devns="v-peer-$netns" # and their addresses ipdef="10.200.$mark.1" ipns="10.200.$mark.2" net="10.200.$mark.0"
确保命名空间不存在。
ip netns del "$netns" 2>/dev/null
创建一个新的网络命名空间。
ip netns add "$netns"
在默认网络命名空间中创建一个 veth 对。
ip link add "$devdef" type veth peer name "$devns"
将一端移动到另一个网络命名空间。
ip link set "$devns" netns "$netns"
配置接口。
ip addr add "$ipdef"/24 dev "$devdef" ip netns exec "$netns" ip addr add "$ipns"/24 dev "$devns"
启动接口。命名空间包含自己的环回设备 lo。我之所以启动它,是因为一般程序可能需要依赖它。
ip netns exec "$netns" ip link set lo up ip netns exec "$netns" ip link set "$devns" up ip link set "$devdef" up
让所有离开命名空间的外部流量都通过 veth 链接。
ip netns exec "$netns" ip route add default via "$ipdef" dev "$devns"
启用 IPv4 转发并启用伪装。
echo 1 > /proc/sys/net/ipv4/ip_forward
链接的文章刷新了各种规则。如果您已经定义了一些规则(转发等),那么三思而后行现在。
# think twice if you should run these iptables -F FORWARD iptables -P FORWARD DROP iptables -t nat -F iptables -t raw -F ip route flush table "$mark"
你将需要这些:
iptables -t raw -A PREROUTING -i "$devdef" -j MARK --set-mark "$mark" ip rule add fwmark "$mark" priority 1000 table "$mark" ip route add default via "$gate" dev "$dev" table "$mark" ip route flush cache iptables -t nat -A POSTROUTING -s "$net"/255.255.255.0 -o "$dev" -j MASQUERADE iptables -A FORWARD -i "$dev" -o "$devdef" -j ACCEPT iptables -A FORWARD -o "$dev" -i "$devdef" -j ACCEPT
检查是否可以从网络命名空间内 ping 某些外部主机。
ip netns exec "$netns" ping 8.8.8.8
注意 DNS(请参阅上面的“可能的问题”)。
在网络命名空间中运行单独的浏览器(请参阅上面的“可能的问题”)。您可能应该以普通用户身份运行它。示例:
ip netns exec "$netns" sudo -u regularuser vivaldi --user-data-dir=/tmp/
示例 2 继续:恢复更改
到目前为止所做的更改都是临时的。如果出现任何问题,只需重新启动即可。
如果你有一些与当前主题无关的规则(转发等),那么三思而后行现在。
# think twice if you should run these
iptables -F FORWARD
iptables -P FORWARD DROP
iptables -t nat -F
iptables -t raw -F
ip route flush table "$mark"
echo 0 > /proc/sys/net/ipv4/ip_forward
你当然可以运行这些:
ip rule del fwmark "$mark" priority 1000 table "$mark"
ip netns del "$netns"
但问题是关于两个接口!现在该怎么办?
在最幸运的情况下,正常启动的浏览器将使用其中一个接口来测试您要测试的地址。如果是这样,您只需按照我的答案,只针对另一个接口,一种方式(示例 1)或另一种方式(示例 2)。
否则,您需要针对这两个接口分别遵循我的答案。您可以选择一种方法(示例 1)或另一种方法(示例 2)或两种方法(示例 1 用于一个接口,示例 2 用于另一个接口)。我会使用两个分离提升的 shell,每个 shell 都有针对相应接口和所选方法调整的变量。以下是提示:
- 设置不同的
dev
变量(非常明显)。 - 设置不同的
netns
变量。 - 如果每个接口都有一个 veth 对(示例 2),那么
- 不同
mark
;记得调整gate
(可能不同也可能相同);其他变量取决于mark
,这会使它们自动不同; - 在应用第二个接口的解决方案时,不要盲目地刷新设置。
- 不同
答案2
没有简单的方法可以做到这一点,因为 Web 浏览器在与操作系统堆栈不同的层上工作,只需挂接到操作系统即可处理路由。
您可能能够在自己的虚拟机中设置一个(或两个)浏览器,每个浏览器都有不同的路由表,以利用备用连接。
如果您有一个网关/远程系统,您可以通过 SSH 连接到它,并且始终只能通过一个连接使用,您可以将一个浏览器实例配置为 sox 代理(或设置常规代理)。
可能可以在您的机器上设置基于策略的路由,(并非简单),然后使用 iptables 中的某些标识符来标记数据包(这是最难解决的部分 - 我能想到的标记数据包的唯一方法是根据所有者,并让每个浏览器由不同的用户启动)并根据标签路由数据包。