一次偶然间,对于校园网防火墙的play,进而引发的安全科普
如何绕过学校防火墙什么是shadowsocks协议sslocal与clinet端的通信sslocal与ssserver的通信ssserver发送给sslocal的数据什么是GFW参考文章GFW的原理GFW做了什么实例翻墙原理一次自建机场的经历参考文章创建server端客户端连接GFW如何检测shadowsocks包
如何绕过学校防火墙
绕过ppsuc校园网防火墙—纯享版什么是shadowsocks协议
参考文章:
sslocal与clinet端的通信
sslocal可以分为两个部分,第一个部分是socks5服务端,它负责监听本地的请求。另外一个部分是信息发送端,它负责向远程的ssserver发送数据包。这个节我们只分析 sslocal 作为 socks5 服务器的这一部分。
- 首先是
client
端发送请求建立连接的请求,发送的数据是05 02 00 01
- sslocal的socks5服务器回复
05 00
,表示不需要认证。
- clinet发送通信目标的ip和port
- sslocal的socks5服务器回复
05 00 00 01 00 00 00 00 10 10
,对比上面的socks5通信协议会知,这里返回的ip是00 00 00 00
,port 是10 10
,这俩都是假的值,因为 sslocal 并没有真实的和client要求的目标地址通信,而是向ssserver发起了请求。
- 接下来就是socks5数据传输过程。client段发送自己的请求,这里是个http请求。
sslocal与ssserver的通信
sslocal发送给ssserver的数据 通过设置filter
tcp.port==7878
获取 sslocal 发送给 ssserver的第一条数据如下:解密后得知是 目标网址+通信控制字段
ssserver发送给sslocal的数据
解密:
直接是目标返回的内容,ssserver没有添加任何额外的头部,直接把原始数据返回
什么是GFW
参考文章
GFW的原理
GFW是一个分布式的入侵检测系统,并不是一个严格意义上的防火墙。不是说每个出入国境的IP包都需要先经过GFW的首可。做为一个入侵检测系统,GFW把你每一次访问facebook都看做一次入侵,然后在检测到入侵之后采取应对措施,也就是常见的连接重置。
检测有两种方式。一种是人工检测,一种是机器检测。你去国新办网站举报,就是参与了人工检测。在人工检测到不和谐的网站之后,就会采取一些应对方式来防止国内的网民访问该网站。对于这类的封锁,规避检测就不是技术问题了,只能从GFW采取的应对方式上采取反制措施。另外一类检测是机器检测,其检测过程又可以再进一步细分:
重建是指GFW从网络上监听过往的IP包,然后分析其中的TCP协议,最后重建出一个完整的字节流。分析是在这个重建的字节流上分析具体的应用协议,比如HTTP协议。然后在应用协议中查找是不是有不和谐的内容,然后决定采用何种应对方式。
GFW做了什么
封IP
一般常见于人工检测之后的应对。还没有听说有什么方式可以直接使得GFW的机器检测直接封IP。一般常见的现象是GFW机器检测,然后用TCP RST重置来应对。过了一段时间才会被封IP,而且没有明显的时间规律。我的推测是,全局性的封IP应该是一种需要人工介入的。这是一种完全不同的封锁方式,虽然现象差不多,都是ping也ping不通。要观摩的话ping twitter.com就可以了,都封了好久了。
其实现方式是把无效的路由黑洞加入到主干路由器的路由表中,然后让这些主干网上的路由器去帮GFW把到指定IP的包给丢弃掉。路由器的路由表是动态更新的,使用的协议是BGP协议。GFW只需要维护一个被封的IP列表,然后用BGP协议广播出去就好了。然后国内主干网上的路由器都好像变成了GFW的一份子那样,成为了帮凶。
如果我们使用traceroute去检查这种被全局封锁的IP就可以发现,IP包还没有到GFW所在的国际出口就已经被电信或者联通的路由器给丢弃了。这就是BGP广播的作用了。
DNS劫持
这也是一种常见的人工检测之后的应对。人工发现一个不和谐网站,然后就把这个网站的域名给加到劫持列表中。其原理是基于DNS与IP协议的弱点,DNS与IP这两个协议都不验证服务器的权威性,而且DNS客户端会盲目地相信第一个收到的答案。所以你去查询facebook.com的话,GFW只要在正确的答案被返回之前抢答了,然后伪装成你查询的DNS服务器向你发错误的答案就可以了。
TCP RST阻断
TCP协议规定,只要看到RST包,连接立马被中断。从浏览器里来看就是连接已经被重置。
我听说这种封锁方式是GFW目前的主要应对手段。大部分的RST是条件触发的,比如URL中包含某些关键字。目前享受这种待遇的网站就多得去了,著名的有facebook。还有一些网站,会被无条件RST。也就是针对特定的IP和端口,无论包的内容就会触发RST。比较著名的例子是https的wikipedia。GFW在TCP层的应对是利用了IPv4协议的弱点,也就是只要你在网络上,就假装成任何人发包。所以GFW可以很轻易地让你相信RST确实是Google发的,而让Google相信RST是你发的。
封端口
GFW除了自身主体是挂在骨干路由器旁路上的入侵检测设备,利用分光技术从这个骨干路由器抓包下来做入侵检测 (所谓 IDS),除此之外这个路由器还会被用来封端口 (所谓 IPS)。GFW在检测到入侵之后可以不仅仅可以用TCP RST阻断当前这个连接,而且利用骨干路由器还可以对指定的IP或者端口进行从封端口到封IP,设置选择性丢包的各种封禁措施。可以理解为骨干路由器上具有了类似“iptables”的能力(网络层和传输层的实时拆包,匹配规则的能力)。这个iptables的能力在CISCO路由器上叫做ACL Based Forwarding (ABF)。而且规则的部署是全国同步的,一台路由器封了你的端口,全国的挂了GFW的骨干路由器都会封。一般这种封端口都是针对翻墙服务器的,如果检测到服务器是用SSH或者VPN等方式提供翻墙服务。GFW会在全国的出口骨干路由上部署这样的一条ACL规则,来封你这个服务器+端口的下行数据包。也就是如果包是从国外发向国内的,而且src(源ip)是被封的服务器ip,sport(源端口)是被封的端口,那么这个包就会被过滤掉。这样部署的规则的特点是,上行的数据包是可以被服务器收到的,而下行的数据包会被过滤掉。
如果被封端口之后服务器采取更换端口的应对措施,很快会再次被封。而且多次尝试之后会被封IP。初步推断是,封端口不是GFW的自动应对行为,而是采取黑名单加人工过滤地方式实现的。一个推断的理由就是网友报道,封端口都是发生在白天工作时间。
实例
ping包
猜测:将你的包发给僵尸路由器
翻墙原理
前面从原理上讲解了GFW的运作原理。翻墙的原理与之相对应,分为两大类。第一类是大家普遍的使用的绕道的方式。IP包经由第三方中转已加密的形式通过GFW的检查。这样的一种做法更像“翻”墙,是从墙外绕过去的。第二类是找出GFW检测过程的中一些BUG,利用这些BUG让GFW无法知道准确的会话内容从而放行,如443端口。
一次自建机场的经历
参考文章
- 项目地址
- 参考文章
- docker仓库地址
创建server端
经历了无数次失败搭建经历,我找到了最方便的方法:万能的docker
万能的docker
当前目录创建文件夹config,进入config 创建config.json文件
# config.json 内容 { "server":"0.0.0.0", "nameserver":"8.8.8.8", "server_port":443, "password":"yourpasswd", "method":"chacha20-ietf-poly1305", "timeout":600, "no_delay":true, "mode":"tcp_and_udp" }
创建
Dockerfile
# Dockerfile 内容 FROM appso/shadowsocks-libev ADD ./config/config.json /etc/shadowsocks-libev/config.json EXPOSE 443
创建
docker-compose.yml
# docker-compose.yml 内容 version: "3" services: shadowsocks: ports: - 443:443 build: . restart: always volumes: - ./config/config.json:/etc/shadowsocks-libev/config.json container_name: Shadowsocks
😇运行命令
docker-compose up -d
客户端连接
我用的clash,编写规则
创建一个文件
xxx.yml
proxies: - name: HK_Shadowsocks_UDP type: ss server: x.x.x.x #服务端ip port: 443 cipher: chacha20-ietf-poly1305 password: yourpasswd udp: true rules: - DOMAIN-SUFFIX,google.com,HK_Shadowsocks_UDP - DOMAIN-KEYWORD,google,HK_Shadowsocks_UDP - DOMAIN,ad.com,REJECT #可以过滤广告 - SRC-IP-CIDR,192.168.1.201/32,DIRECT - IP-CIDR,127.0.0.0/8,DIRECT - IP-CIDR6,2620:0:2d0:200::7/32,HK_Shadowsocks_UDP - GEOIP,CN,DIRECT - "MATCH,DIRECT"
clash 项目地址:
导入clash
GFW如何检测shadowsocks包
一篇非常好的文章
在Shadowsocks中, 客户端与服务端之间的连接是加密的。 而且这种加密后, 观察者看到的全部都是密文。 这一点与TLS不同。 TLS的报头中含有明文。 而Shadowsocks流量则全部是密文。 如果你观察就会发现Shadowsocks的流量 就好像一列列均匀随机的字节。 而其就是这么设计的。 这样的设计意味着,你不能仅仅用一个 简单的正则表达来匹配出所有的Shadowsocks流量。
防火长城 使用在TCP流中数据包的长度和熵作为 其识别Shadowsocks流量的第一步
防火长城识别Shadowsocks流量的过程分两步: 第一步被动,第二步主动。
第一步,防火长城流量分析出 其怀疑是Shadowsocks的连接。
第二步中, 防火长城会假装成Shadowsocks客户端, 从自己的IP地址主动去连接它怀疑的服务器。 然后观察被探测的服务器会怎样回应。 你可以把第一步的目的想成“怀疑”, 而第二步的目的则为“确认”。
主动探测是为了在识别中增加准确率,降低成本。 如果你仅仅用流量分析被动地识别Shadowsocks流量, 那么假阳性可能会高得不可接受。 而另一方面,如果你对每一个经过防火长城的连接, 都进行主动探测的话, 那你又会因为需要发送的 主动探测太多而管不过来。 因此可以把步骤一想成是对步骤二的预先过滤。