如何强制 Chrome 使用特定的网络接口(例如 tun1)?
某些程序例如curl
具有选择特定网络接口的选项。
在 Windows 中,强制绑定IP允许您强制应用程序使用特定的网络接口/ IP 地址。
我想知道 Ubuntu/Linux 中是否有解决方案。
或者,由于我们可以在 Chrome 中设置代理;我们可以将本地 IP 重定向到网络接口或反之亦然吗?
答案1
这是网络命名空间的完美用例,网络命名空间自 2016 年或更早以来就已成为 Linux 的一部分。以下是带有注释的示例,可帮助您入门:
# enable forwarding
sysctl -w net.ipv4.ip_forward=1
# create the network namespace
ip netns add chrome
# create the virtual nic and it's peer
ip link add chrome type veth peer name chrome-peer
# assign the peer to the network namespace
ip link set chrome-peer netns chrome
# assign an ip address
ip addr add 192.0.2.1/24 dev chrome
# bring up interface
ip link set chrome up
# similar network setup for network namespace
ip netns exec chrome ip link set lo up
ip netns exec chrome ip addr add 192.0.2.2/24 dev chrome-peer
ip netns exec chrome ip route add default via 192.0.2.1
ip netns exec chrome ip link set chrome-peer up
# allow forwarding and add enable NAT
iptables -I FORWARD -s 192.0.2.0/24 -j ACCEPT
iptables -t nat -I POSTROUTING -s 192.0.2.0/24 -o tun1 -j MASQUERADE
# pop a shell in the namespace
ip netns exec chrome bash
# check that you're in the namespace
ip netns identify
# run the browser as your local user
runuser -u Barry google-chrome
答案2
背景
Linux 可以SO_BINDTODEVICE
选择将套接字绑定到特定的网络接口。
主意
Chromium 使用 libc 函数来调用系统调用,包括connect()
用于执行网络请求的系统调用。我们可以在执行系统调用之前修补connect()
要调用的函数。这可以通过环境变量预加载共享库来实现。setsockopt(SO_BINDTODEVICE)
connect()
LD_PRELOAD
最小工作示例:
连接.c
#define _GNU_SOURCE
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#define IFACE_NAME "tun0"
#define IPV6_TO_BIND "fddd:bbbb::2"
static void set_bind_addr6(int fd)
{
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
inet_pton(AF_INET6, IPV6_TO_BIND, &addr.sin6_addr);
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
}
int connect(int fd, const struct sockaddr *daddr, socklen_t addrlen)
{
int family = daddr->sa_family;
if (family == AF_INET || family == AF_INET6) {
if (family == AF_INET6)
set_bind_addr6(fd);
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, IFACE_NAME, sizeof(IFACE_NAME));
}
return syscall(__NR_connect, fd, daddr, addrlen);
}
调整IFACE_NAME
和IPV6_TO_BIND
您的机器设置。如果您不想使用 IPv6,则可以省略 IPv6 绑定代码。
如果您希望使用 IPv6,则需要 IPv6 绑定,因为调用者设置了错误的绑定地址。它还可以帮助您选择要用于传出连接的 IPv6 地址。
IPv4 不需要绑定。
用法
ammarfaizi2@integral2:/tmp$ gcc -fpic -fPIC -Wall -Wextra -shared -O3 connect.c -o connect.so
ammarfaizi2@integral2:/tmp$ export LD_PRELOAD="/tmp/connect.so"
ammarfaizi2@integral2:/tmp$ /opt/google/chrome/chrome
在 Ubuntu 22.04 上使用 IPv4 和 IPv6 网络测试并运行良好
更新
2023 年 6 月 30 日:
- 添加 IPv6 支持。
- 删除内联汇编(使其可移植到其他架构)。