之前逛V2EX 看到一个网友的帖子:“请教公司内部如何实现无感知跨境加速”,把海外IP 全部走到代理网关,维护成本比较高。如果只是简单的Web 加速,DNS 劫持+SNIProxy 是更轻量的方法。
~~有Fortinet、Panabit的土豪无须接着看 🤑~~
这个方案的局限:
- 只能加速http、https 流量;
- 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 clients being proxied to wrong host. #178
- HTTP代理访问Github会经常出现 Fastly error: unknown domain: github.com. #422
- NIproxy doesn't support http2 or SPDY explicitly,
看起来和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 自己会重试;
- 我选这个
参考资料: