fangpsh's blog

轻量级办公室无感知跨境加速方案

之前逛V2EX 看到一个网友的帖子:“请教公司内部如何实现无感知跨境加速”,把海外IP 全部走到代理网关,维护成本比较高。如果只是简单的Web 加速,DNS 劫持+SNIProxy 是更轻量的方法。

~~有FortinetPanabit的土豪无须接着看 🤑~~

这个方案的局限:

  1. 只能加速http、https 流量;
  2. github.com(http2)似乎有异常,见下文解决方法。

按网友说的联通/电信的MPLS,1000元/M/(月?),如果是我的话,就会搞几个机场账号,一个月成本百来块解决。

当然我牢记前辈们的血泪教训:在工作场合中,能用钱解决的,尽量用钱(乙方)解决,要不然就是给自己找事了🐕。

说回正事,画个草图:

             ┌──────────┐   query:www.google.com ┌───────────┐
             │          ├────────────────────────►           │
             │  client  │                        │ local dns │
             │          ◄────────────────────────┤           │
             └───┬───▲──┘    A:192.168.11.11     └───────────┘
                 │   │
                 │   │
                 │   │
         http req│   │ http rsp
                 │   │                      ┼
                 │   │
                 │   │
             ┌───▼───┴──────────┐
             │                  │
             │    proxy         │
             │  192.168.11.11   │
             └───────────────┬──┘
                             │
                             │internal
                             │
       ┌─────────────────────┴────────────────────┐
       │                                          │
       │ ┌───────────┐         ┌────────────┐     │
       │ │ SNIPROXY  │  OUTPUT │            │     │
       │ │ http:80   ├────────►│   CLASH    │     │
       │ │ https:443 │ IPTABLES│   TPROXY   │     │
       │ └───────────┘         └────────────┘     │
       │                                          │
       │                                          │
       └──────────────────────────────────────────┘

找一台机器装上clash/v2ray/sing-box 等,下面以clash为例。

local dns 用adguard-home、bind、dnsmasq、pdns-recursor都可,把要加速的子域名劫持解析到代理机IP。

SNIProxy 配置

官方仓库拉代码编译安装,或者发行版仓库内找找。配置就一句话,没什么好说的,如果不想有人随意本地host 下域名就能走这个代理传透出去,就写下具体域名,语法官方手册。当然也可以在clash 那里控制。

table http_hosts {
    .* *:80
}

table https_hosts {
    .* *:443
}

Clash 配置

就一句话,其他和日常配置没差别:

tproxy-port: 7891

若用非特权用户起,clash.service记得设置Capability。

CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH

另外在部署此类代理时,建议拒绝掉内网域名(内网地址),以免增加追踪审计复杂度。

- GEOIP,LAN,REJECT
- DOMAIN-SUFFIX,oa.com,REJECT
- ...

主机配置

主要涉及策略路由和iptables,正常只需要设置OUTPUT chain 即可,但是为了解决下文github的问题,也配置下FORWARD。

让特殊标记的包流向本机:

# 记得配置开启启动生效
ip route flush table 100
ip route add local default dev lo table 100
ip rule add fwmark 1 table 100

iptables,抄网友的,记得做持久化:

iptables -F
iptables -X
iptables -t nat -F
iptables -t mangle -F
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -p tcp  -j ACCEPT

# RETURN LOCAL AND LANS
iptables -t mangle -A clash -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A clash -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A clash -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A clash -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A clash -d 192.0.0.0/24 -j RETURN
iptables -t mangle -A clash -d 192.0.2.0/24 -j RETURN
iptables -t mangle -A clash -d 198.18.0.0/15 -j RETURN
iptables -t mangle -A clash -d 198.51.100.0/24 -j RETURN
iptables -t mangle -A clash -d 203.0.113.0/24 -j RETURN
iptables -t mangle -A clash -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A clash -d 100.64.0.0/10 -j RETURN
iptables -t mangle -A clash -d 224.0.0.0/4 -j DROP
iptables -t mangle -A clash -d 240.0.0.0/4 -j RETURN
# FORWARD ALL
iptables -t mangle -A clash -p udp -j TPROXY --on-port 7891 --tproxy-mark 1
iptables -t mangle -A clash -p tcp -j TPROXY --on-port 7891 --tproxy-mark 1

#iptables -t mangle -A OUTPUT -j clash
iptables -t mangle -A PREROUTING -j clash


iptables -t mangle -N LOCAL_DIVERT
iptables -t mangle -A LOCAL_DIVERT -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A LOCAL_DIVERT -p tcp -j MARK --set-mark 1
iptables -t mangle -A LOCAL_DIVERT -p udp -j MARK --set-mark 1

iptables -t mangle -A OUTPUT -m owner ! --gid-owner { 运行clash 程序的GID}  -j LOCAL_DIVERT

如果尝试写:iptables -t mangle -A OUTPUT -j clash 会出现错误:

iptables v1.8.7 (nf_tables):  RULE_APPEND failed (Invalid argument): rule in chain OUTPUT

网友解释:

由于 tproxy 只能工作在 PREROUTING 链,从本机发出去的数据包会直接通过 OUTPUT 链出去了,本机数据包没有机会走一下 PREROUTING 链。 作者:靛青K https://www.bilibili.com/read/cv14088928/ 出处:bilibili

sysctl 开启ipv4包转发:

echo "1" > /proc/sys/net/ipv4/ip_forward
#建议配置/etc/sysctl.conf中,开机生效。

github.com 的问题

如果把github.com 劫持到sniproxy,不久浏览器就会出现以下错误:

Fastly error: unknown domain: github.com. Please check that this domain has been added to a service.
Details: cache-hkg17926-HKG

搜到的一些issue:

看起来和http2 长连接有关,暂时没精力(能力)细究,看到有一个PR是能针对特定域名指定一些,但是没合。

那就只能倒回去用网关的模式解决了。

dig 了下github.com 的域名,集中在这2个段,添加策略路由,把下一条指到代理机。

140.82.112.0/22
20.205.192.0/18

内网搭建一个uptime kuma 或者megaease/easeprobe,对github.com 进行curl 探测,发现异常再加新的IP。

sniproxy+v2ray+redirect

v2ray(dokodemo-door)+ redirect 也行,简单贴下配置:

{
    "log": {
        "loglevel": "warning",
        "access": "/var/log/v2ray/access.log",
        "error": "/var/log/v2ray/error.log"
    },
    "inbounds": [
        {
            "tag":"transparent",
            "port": 12345,
            "protocol": "dokodemo-door",
            "settings": {
                "network": "tcp,udp",
                "followRedirect": true
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            },
            "streamSettings": {
                "sockopt": {
                  "tproxy": "redirect"
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vmess",
            "settings": {
                ...
            },
            "streamSettings": {
                "sockopt": {
                    "mark": 255
                }
            },
            "tag": "proxy"
        }
    ]
}
#!/bin/bash

iptables -F
iptables -t nat -F
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT


iptables -t nat -N V2RAY
iptables -t nat -A OUTPUT -p tcp -j V2RAY

iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12345

iptables -t nat -A PREROUTING -p tcp -j V2RAY

容灾

这些网站本来就不存在,容什么灾?😂

  • LVS 传统做法
    • 或者土豪有F5之类
  • 配置多个代理机,local dns 那里返回多个A记录,Chrome 自己会重试;
    • 我选这个

参考资料: