方法 1-OpenVPN

方法 1-OpenVPN

在 ubuntu 16.04 上,我想根据浏览器中输入的域名通过直接互联网eth0或 VPN 路由我的流量。原因是本地站点要么速度慢,要么依赖于位置。tun0

我知道内核路由表是基于 IP 的,域名通常在软件层解析,但由于 Linux 是一个脚本友好的平台,我希望找到一种解决方法。不过,我不知道如何编写这样的脚本。

到目前为止,我发现该dig example.com +short @8.8.8.8命令将列出与域关联的 IP,并且我发现该sudo route add -net 8.8.8.8 netmask 255.255.255.255 gw 192.168.2.1命令将绕过给定 IP 的 VPN(其中 192.168.2.1 是我的默认值eth0)。有人能不能帮我模板一个脚本,该脚本读取包含域名的文件并在系统启动时输入路由规则。允许屏蔽子域可获得加分*.example.com

如果有更简单的方法来解决这个疯狂的问题,我会接受它作为解决方案。

注意:我可以非常轻松地将 IP 硬编码到文件中,/etc/network/interfaces但这样一来它们就变得难以管理了。我还尝试将我所在国家的所有已知 IP 硬编码到这个文件中,但效果很差,而且启动时间也比较延迟。

答案1

我建议您避免基于域名管理路由(顺便说一句,也不可能解析通配符子域名,不管这是否是加分项:D)

更详细地描述一下,你不应该这样做,因为:

  1. 有些域名会不时更改其 IP,

  2. 子域名中无法匹配通配符

  3. 不可能知道/获取任何域的所有子域

  4. 任何随机子域名都可以有任意随机 IP 地址。

因此,浏览器插件(和/或自定义本地代理,如 squid)的解决方案是解决您的问题的最佳选择。

但是,我猜,“FoxyProxy”插件(它最初是 Firefox 插件,但据我所知,也有一个 Chrome 版本)正是您想要的。

另外,回答您关于“FoxyProxy 是付费服务并且您已经拥有 vpn”的通知:

福克斯代理是付费服务,但 FoxyProxy 不是。

FoxyProxy 是一个插件,适用于主流浏览器:

标准版 (Firefox)|基础版 (Firefox)

标准版 (Chrom{e,ium})|基础版 (Chrom{e,ium})

因此,如果您想通过 VPN 访问某些域,您应该:

  1. 为 foxyproxy 编写规则,以便通过 squid 实例获取域列表

  2. 和/或编写 squid 的规则列表

  3. 捕获 http/https 流量不拥有通过 squid 使用 iptables 并通过规则将其指向 squid,如下所示:

iptables -m owner -m multiport -t nat -A OUTPUT ! -o lo ! --uid-owner $squid_user_id -p tcp --dports 80,443,8080,... -j REDIRECT --to-ports $SQUID_PORT

--syn可能需要选项-p tcp

  1. 捕获 http/https 流量拥有由 squid 处理,并使用如下规则将其标记为下次路由到 VPN:
iptables -A OUTPUT -m owner --uid-owner $squid_user_id -j MARK --set-mark 11
echo 11 forcevpn >> /etc/iproute2/rt_tables
ip rule add fwmark 11 table forcevpn
ip route add default via 10.0.0.1 table forcevpn

您的 VPN 网关在哪里。或者,如果您没有网关,并且只想将所有流量推送到 VPN 接口,10.0.0.1则可以使用dev $VPN_IF而不是。via 10.0.0.1

  1. 可选地,你可能需要运行sudo sysctl ipv4.conf.all.rp_filter =0

===

还有一件事情:

如果您想对非 http(s) TCP 流量执行相同的魔法,您将需要类似代理链之类的东西,并执行类似的捕获魔法。

而且,如果你想用 UDP 来实现这个魔法,我有一个坏消息:我不知道有任何代理能够代理 UDP(由于这个协议的性质):)

⇓⇓⇓ 编辑 ⇓⇓⇓

如果您想要相反的操作(默认 gw = vpn,并直接通过 ISP 统治一些域),则可以:

  1. 为 foxyproxy 编写规则,以便通过 squid 实例获取域列表

  2. 捕获流量拥有由 squid 处理,并使用如下规则将其标记为下次以另一种方式路由:

iptables -A OUTPUT -m owner --uid-owner $squid_user_id -j MARK --set-mark 11
echo 11 novpn >> /etc/iproute2/rt_tables
ip rule add fwmark 11 table novpn
ip route add default via ${ISP_GW} table novpn

您用来将流量路由到 VPN 服务器的网关在哪里。如果某些用户使用 pptp 连接到互联网,他们ISP_GW可能希望使用dev ppp0(或ppp1, ..., pppN) 而不是 。via ${ISP_GW}

答案2

基于目标域的路由并非不可能,而且,使用正确的工具,也不是那么难。

我将介绍几种几乎不需要特殊客户端配置的方法。这些方法都假设您使用 OpenVPN 进行连接。这应该可以通过其他 VPN 实现,但在启动 VPN 后可能需要更多手动配置。

为了举例说明,我将使用域“example.com”、“us1.example.com”、“us2.example.com”和“geoblocked.com”作为我们想要通过非 VPN 接口路由的域。

所有命令都应以 root 身份运行。

方法 1-OpenVPN

仅当您确定所路由的 IP 地址具有永不改变的静态 IP 时,我才会推荐这样做。

优点:

  • 极其简单

缺点:

  • 仅对具有以下 IP 的域名可靠绝不改变
  • 需要为每个域和子域提供明确的条目

方法:

将以下行添加到您的 OpenVPN 配置:

route example.com     255.255.255.255 net_gateway
route us1.example.com 255.255.255.255 net_gateway
route us2.example.com 255.255.255.255 net_gateway
route geoblocked.com  255.255.255.255 net_gateway

重新启动 OpenVPN。

就是这样,但是如果这些 IP 地址发生变化,您将必须重新启动 VPN。

笔记:有些消息来源说您还需要指定allow-pull-fqdn,但根据我的经验,情况似乎并非如此。YMMV。

方法 2 - 基于策略的路由

基于策略的路由是根据某些标准进行路由的能力;通常是源地址或协议,但在这种情况下,我们将在路由之前检查目标域名并使用标记的数据包(“fwmark”)。

因此,我们首先需要做的是为您的 VPN 路由数据包创建一个单独的表,以便我们可以标记那些通过 VPN 的数据包,并通过非 VPN 接口传递标记的数据包。(请记住,这只是一种方法,还有许多其他方法可以实现这一点,例如让 VPN 通过主表正常进行路由,并为非 VPN 流量创建一个单独的表。)

您的内核必须足够新并且具有适当的模块,尽管现代系统可能在其默认内核中已有它们。

名称“vpn_table”(路由表名称)以及数字“201”(路由表ID)和“3”(fwmark)是任意选择的。

创建新的路由表(以 root 身份):

echo 201 vpn_table >> /etc/iproute2/rt_tables

配置 OpenVPN:

在某处创建以下脚本(我将其命名为“/etc/openvpn/client/setup-routing”)并使其可执行:

#!/bin/bash
ip route add 0.0.0.0/1 via $route_vpn_gateway dev $dev scope global table vpn_table
ip route add 128.0.0.0/1 via $route_vpn_gateway dev $dev scope global table vpn_table
sysctl -w net.ipv4.conf.$dev.rp_filter=2

# You can optionally leave the next two lines out but run the `ip rule add`
# command at each boot instead
ip rule del fwmark 3 table vpn_table &>/dev/null # This might fail but that's ok
ip rule add fwmark 3 table vpn_table

OpenVPN 将把上述脚本中的变量填充为环境变量。另请注意,这会将路由设置为全部通过“vpn_table”路由表中的 VPN 网关获取地址。如果您的 VPN 设置需要更复杂的路由,请参阅 OpenVPN 文档并进行相应调整。

将以下内容添加到您的 OpenVPN 配置:

## Policy routing
route-noexec
script-security 2
route-up /etc/openvpn/client/setup-routing

“route-noexec”行允许 OpenVPN 从服务器获取路由,但阻止它实际填充路由。而是调用路由脚本。“script-security 2”是调用用户定义的脚本所必需的。

这就是路由标记数据包所需的所有设置,但我们需要设置一种实际标记数据包的方法。两个选项是使用 dnsmasq 和 ipset,或设置 squid 代理。

方法 2a - 使用 ipset 和 dnsmasq 进行基于策略的路由

如果您已经在基于 dnsmasq 的路由器上运行此方法,或者您的客户端不支持代理配置,我建议您使用此方法。这实际上与缓存 DNS 相同,每当查找域名时都会更新路由表。

优点:

  • 处理子域名
  • 适用于无法访问代理的设备(存在吗?)

缺点:

  • 不处理引荐来源字段(参见方法 2b)
  • 需要复杂的 ipset 和 iptables 配置
  • 需要将 VPN 连接系统设置为路由器(需要专用接口)
  • 我不知道 ipset 的可扩展性如何(我的用例是针对整个 ccTLD)

这假设您已经配置并设置了 dnsmasq,并将其作为连接到专用接口“eth1”的客户端的网关和 DNS 服务器。

创建 ipset:

ipset create SKIP_VPN_IPSET iphash

告诉 iptables 标记 ipset 数据包(注:这必须做完了创建 ipset 列表):

# Mark ALL packets coming in on eth1 - change this to the interface dnsmasq listens on
iptables -A PREROUTING -i eth1 -t mangle -j MARK --set-mark 3

# REMOVE mark on any addresses that match our ipset
iptables -A PREROUTING -t mangle -m set --match-set SKIP_VPN_IPSET dst -j MARK --set-mark 0/3

笔记:每次启动时都必须运行上述命令(ipset和)。或者,您的操作系统可能会提供一些用于保存/恢复 iptable 规则和 ipset 的选项。iptables

笔记2:有记录表明存在相反的情况! --match-set,但当我尝试时,所有数据包都消失了。

将以下内容添加到您的 dnsmasq.conf:

ipset=/example.com/geoblocked.com/SKIP_VPN_IPSET

显然,无论你想要路由哪个域名,都要调整该行。这还将添加全部子域名添加到 ipset,因此您无需明确指定它们。即使使用 TLD 也可以。

重新启动 dnsmasq 并设置您的客户端以使用 VPN 连接系统作为网关和 DNS(如果它设置为 DHCP 服务器,则应该是隐含的)。

方法 2b - 基于策略的路由使用 squid

这是我最喜欢的方法,并且适用于我的 PS4 和我用来连接的其他设备。

优点:

  • 处理子域名
  • 处理引荐来源字段
  • 不需要更换现有的路由器
  • 客户端(浏览器)可以选择使用或不使用

缺点:

  • 客户端必须支持代理连接

这假设您有一个可运行的 Squid 设置并且具备 Squid 配置的基本知识。

将以下行添加到 squid.conf:

# redirect example domains
acl domain_to_remote_proxy dstdomain .example.com
acl ref_to_remote_proxy referer_regex [^.]*\.example.com.*

# redirect geoblocked domain
acl domain_to_remote_proxy dstdomain .geoblocked.com
acl ref_to_remote_proxy referer_regex [^.]*\.geoblocked.com.*

# mark packets that we want routed through the VPN
tcp_outgoing_mark 0x03 !ref_to_remote_proxy !domain_to_remote_proxy

请注意,每个域名有 2 行,并且子域名是匹配的。第一行检查目标域名,第二行匹配“Referer”标头。这很有用,因为浏览器在获取网页上的内容(例如图像、CSS 或 javascript)时会发送 referer;这意味着即使网站请求的内容托管在不同的域名上(例如 example-cdn.com),它也会通过非 VPN 地址路由。

在客户端上,像平常一样设置连接,但设置代理设置以使用此系统的代理服务器和端口。大多数设备(包括游戏机)允许系统范围的配置。在 PC 上,大多数浏览器都可以配置为使用独立于系统设置的代理。

最后说明 - 我的用例实际上是通过 VPN 路由特定域,而通过非 VPN 路由其他所有域。方法与上述方法类似,但反过来。

答案3

Squid 不支持 socks(比如 ssh 隧道)... 有一个选项可以构建带有 socks 支持的 squid,但很难让它工作。

私有网络可以胜任

  • 支持父母袜子
  • 支持http/https代理
  • 支持推荐人
  • ETC。

Privoxy 设置:

  1. 安装 privoxy

  2. 编辑配置文件(删除所有内容/etc/privoxy并添加/etc/privoxy/config

    user-manual /usr/share/doc/privoxy/webserver/user-manual
    confdir /etc/privoxy
    logdir /var/log/privoxy
    actionsfile default.action
    filterfile default.filter
    logfile logfile
    toggle  1
    enable-remote-toggle  0
    enable-remote-http-toggle  0
    enable-edit-actions 0
    enforce-blocks 0
    buffer-limit 4096
    enable-proxy-authentication-forwarding 0
    forwarded-connect-retries  0
    accept-intercepted-requests 0
    allow-cgi-request-crunching 0
    split-large-forms 0
    keep-alive-timeout 5
    tolerate-pipelining 1
    socket-timeout 300
    listen-address  127.0.0.1:8888
    forward-socks5 .whatismyipaddress.com 127.0.0.1:8080 . 
    forward-socks5 .whatismyip.com 127.0.0.1:8080 . 
    
  3. 重启服务

    systemctl start privoxy

  4. 在客户端应用程序上设置 privoxy 代理

  5. 如果你想要路由 referrer,请添加 default.action 和 default.filter,你可以使用以下命令进行测试http://www.play-hookey.com/htmltest/带有 html 代码

    <a href="http://amibehindaproxy.com/">test-ip</a></br>
    <a href="http://www.stardrifter.org/cgi-bin/ref.cgi">test-referrer</a>  
    
  6. default.action 和 default.filter

    默认操作

    {+client-header-tagger{referer}}
    /
    
    {+forward-override{forward-socks5 127.0.0.1:8080 .}}
    TAG:.*?hookey.com 
    

    默认过滤器

    CLIENT-HEADER-TAGGER: referer
    s@^Referer:.*?$@$0@i
    
  7. 重启 privoxy 服务

答案4

作为配置 iptables 和浏览器扩展的替代方案,有一个工具解决方案v2ray. 适用于所有主流操作系统。

v2ray旨在用作绕过 GFW 的代理工具。它支持多种 VPN 协议,包括 ShadowSocks、SOCKS5、HTTPS……此外,它还可以配置为基于域名路由流量。

自从问了这个问题。我托管了自己的 VPN,并在所有端点使用 v2ray。我的本地系统配置为将所有网络流量重定向(使用 iptables)到本地 v2ray 服务,然后将其转发到我的 VPN 服务器。我还配置了一个 SOCKS5 侦听器并使用名为 的浏览器扩展SmartProxy来过滤特定域。v2ray 能够过滤域,但我发现浏览器方法更容易配置。

相关内容