SNI代理:让舍友别去百度了
本文,老规矩,前半部分是严重偏题的
前半部分笔者主要想讲一下关于目前『轻度非技术党翻墙』的现状,如果你想知道笔者是如何实现SNI代理的,可以直接打开目录跳转
前言
新学期开始了,苦逼大学生的生活还得继续
这个学期学校加开了Linux课程,笔者隐隐约约觉得有些问题。Linux这玩意说白了你得整天和一个黑框框打交道,出了什么问题你得拿着报错信息去问。不过你也知道的,以百度为代表的一大堆国内搜索引擎跟没有一样,搜索出来的内容垃圾的要死,要想真要玩通Linux,最好手边常备咕噜咕噜——通常意味着你可以顺便去wikipedia,StackOverFlow,GitHub,以及其他
自己电脑肯定是没问题的,但是还是苦了那帮舍友。上学期给做了个小软件,打开之后就可以连接『专线网络』,其基本原理也就是指定Windows上的系统代理到宿舍网内的服务器。用起来倒是没啥毛病,但是每次使用都要开关,而且电脑一旦移动到宿舍网之外,不关掉还上不了网(此代理服务器不存在)。最好的方法当然还是透明代理,让一个设备可以无感接入代理,当然最主要的是可以无感退出代理
轻度翻墙的现状
那么现在开始偏题。
墙就在那,当你想获取什么信息都时候,你就得绕过他
近几年来,各种『小厂VPN』出现在各种应用商店里面。这里暂且不讨论这些玩意的稳定性,隐私性什么的(就这两个属性其实都可以单开很长一篇文章),他们能流行起来的一个很重要的原因是以尽量简单的方式解决了最直接的简单需求
什么是简单需求,笔者在这里给一个可能不准确的定义:『浏览被墙的网站/APP』。前者好说,就是HTTP(s),后者,虽然我们说APP是C/S架构的产物,但是实际上目前很客观的来说,为了实现跨平台以及快速开发,以及尽可能复用技术栈,很多APP实际上也是B/S架构;或者是C/S,但是和服务器通过HTTP(s)的API来交换信息
这就导致一个现象:如果某个『小厂VPN』仅仅实现了对80/443的代理,那么他的目标客户90%以上概率不会发现任何异常,如果增加对常用HTTP(S)端口的代理,
这个覆盖率可以提高到95%以上。这一部分客户的需求一般都是:
- 上咕噜咕噜(包括里面能打开的一些网站,比如stackOverflow)查资料
- 到Web版Gmail上收发邮件
- 刷刷推特,FaceBook
- Telegram,Line,聊天
- 色图(或者说正经的,访问成人内容)
这些应用完美符合了上面对于简单需求的定义
外贸厂的日子
还有一类比较特殊的翻墙用户:各种做外贸的跨境电商商家。他们需要把自己的产品发布到亚马逊,tiktok等平台,以及需要和外国的用户进行生意上的交流。但是毕竟术业有专攻,他们很多时候并不懂得如何折腾翻墙,只是希望有些设备可以插上/打开就能用,最好还能带起来一堆电脑,方便多路开展业务
因此有些商家会偷偷的出售『翻墙路由器』,也有些运营商会(当然不会明面上宣传)出售一些小微企业的出海专线,做了很多审计之后卖给这些制衣厂,让他们可以流畅地上亚马逊等网站
很明显,对于这一类商家而言,他们看中的是能够满足需求。你说你的专线可以高速传输ICMP,你的专线可以传输L2TP/IPSec数据,没用!他们只要能访问网站,能进行Tiktok直播,就行了
宿舍的SNI代理
舍友和上面的轻度翻墙用户其实差不多,他们只需要一些可以访问网页的东西就行了,但是最好可以做到无感,也可以做到不需要另外安装软件
SNI代理,此时就成了一个非常简单的方案,其胜在简单,稳定,好实现,对于被代理的网站不会出现DNS泄露的情况
当然,凡事有两面性,SNI代理的缺点就是只能实现对于HTTP(S)的代理,而且如果你的客户端很先进,实现了eSNI,那么就没办法嗅探到目标地址了(当然就目前而言,这个情况还不算严重,可能过几年就用不了了)
有,但问题不大
网上(包括SNIProxy的issues区)有人提到,H2的连接复用(浏览器发现两个域名有同样的IP,且共用泛域名证书的时候,可能不会发起新连接)可能导致SNI Proxy无法正确地路由被代理的流量
但实际上,这个问题被HTTP 421代码给缓解了。当服务器收到类似这样的错误请求的时候,可以返回421错误代码,指示客户端强制断开并重连,此时SNI Proxy就可以正确的路由流量了
此外还有一点要注意的是:SNI代理服务器不建议安装在公网上,主要还是两方面:首先SNI代理很难实现有效鉴权,除非你限制源IP(这也就是为什么那些『DNS流媒体解锁服务』都得报一个公网IP上去授权;其次,SNI是明文的,很容易被半路上的某个设备给拦截了,然后嘛......
所以,内网找一台机器装就是了
DNS的设置
SNI代理的核心思想是通过流量的Host/SNI信息,来路由流量,那么前提就是先把流量都送到代理服务器上,这就需要DNS来协助了。DNS把需要代理的域名都解析为代理服务器的地址,流量就可以被送到服务器上
笔者给小路由安装的DNS服务器是AdGuardHome,内置了DNS改写功能,只需要在自定义规则那添加如下规则:
||example.com^$dnsrewrite=PROXY_IP
example.com
就是需要被代理的域名(只填写一级域名就行,||
代表匹配子域名),PROXY_IP
就是安装了SNI代理的服务器地址。如果有多个域名需要代理,那么就依葫芦画瓢就行
写好,保存,用dig或者nslookup命令检查,可以看到需要被代理的域名已经返回了代理服务器的地址,同时在ADG的日志中,也可以看到蓝色的『改写』提示
SNI代理服务器
GitHub上面有个项目是SNI Proxy,可以用,但是比较久没有更新了。笔者采用的是gost,就最新版的那个。设置项写着是SNI代理,但是实际上也可以读取Host信息实现代理,因此就不必额外用其他HTTP服务器实现301跳转了
下载好gost之后,创建配置文件:
services:
- name: sni-443
addr: :443
admission: lan-only
bypass: no-loop
handler:
type: sni
chain: outbound
listener:
type: tcp
- name: sni-80
addr: :80
admission: lan-only
bypass: no-loop
handler:
type: sni
chain: outbound
listener:
type: tcp
# 此处是上级代理,可以用gost支持的,同时可以连接到目标网站的代理
# 比如此处用的是HTTP代理,连接到clash-meta
chains:
- name: outbound
hops:
- name: hop-0
nodes:
- name: out-http
addr: ":7890"
connector:
type: http
dialer:
type: tcp
# 此处防止被人盗用SNI代理
# 尤其是WAN侧,校园网的其他用户盗用
admissions:
- name: lan-only
whitelist: true
matchers:
- 10.1.1.0/24
# 此处设置防止回环
# 回环:试试访问127.0.0.1:80?分分钟塞爆内存和CPU
bypasses:
- name: no-loop
matchers:
- 0.0.0.0/32
- 127.0.0.0/8
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
log:
output: stdout
level: warn
format: text
写好,保存,启动(systemctl,或者懒人方法,screen,悉听尊便),尝试在客户端访问一下,可以发现,目标网站已经可以正常代理了
写在最后
啰啰嗦嗦写了些东西,主要还是提到一下SNI在目前还是高可用的,在确定自己确实需要使用类似tproxy之类的全端口透明代理之前,不妨先试试SNI代理,也许也能带来惊喜
(完)