WireGuard wg-quick PostUp的高级玩法

真的很高级。

wg-quick是WireGuard用来启动网络设备的**脚本**。

注意了,迄今为止,wg-quick是用bash写的一个脚本,不知道未来会不会变,至少目前shebang是

Continue reading “WireGuard wg-quick PostUp的高级玩法” »

WireGuard wg-quick PostUp的高级玩法 by @sskaje: https://sskaje.me/2017/06/wireguard-wg-quick-postup%e7%9a%84%e9%ab%98%e7%ba%a7%e7%8e%a9%e6%b3%95/

另类方法劫持手机流量

实际上看,CharlesProxy并不能100%地“劫持”到手机的https流量,说“劫持”可能不太合适,因为CharlesProxy根本都不把这个443端口的请求在请求列表里显示出来。

这次玩的是GameLoft的Asphalt Xtreme,从google play store下载下来玩后,发现游戏的免费门槛太高了,随便玩玩不消费就进行不下去。
之前玩GameLoft的游戏改数据,都是iPhone下备份数据,修改存档,因为那些游戏有存档。但是这次主要用了Android,且没有root。试过iOS的版本,文档里没看到明文数据(txt/bin都没有)。本来想找个游戏修改器试试,后来没继续下去。

具体选型上,我是在EdgeRouter Lite上跑了个redsocks。因为是临时方案,所以不考虑使用EdgeOS/VyOS的配置语法,而直接使用了iptables。
协议分析和数据劫持,使用了CharlesProxy,因为CharlesProxy支持socks代理,还自带”Rewrite”功能,可以做简单字符串替换和正则替换。

环境:
路由 EdgeRouter Lite 固件1.9.1,IP 192.168.1.1,基于debian wheezy
Redsocks,0.4+dfsg-1,下载地址 https://packages.debian.org/wheezy/redsocks

电脑 MacBook Pro macOS 12 + CharlesProxy 4.x, IP 192.168.1.20,HTTP端口8888,Socks端口8889

手机 Mate 9,IP 192.168.1.40;

路由端

ERL是mips/mips64,从debian官网下载mips版的deb,直接 dpkg -i 安装即可。如果路由上没有libevent,还得下载装一下。
安装好redsocks后,修改 /etc/default/redsocks,修改START=yes。
直接基于 /etc/redsocks.conf 修改

改local_ip的原因是因为我iptables偷懒了。反正用完就关,无所谓。

使用 /etc/init.d/redsocks start启动服务。

iptables
只劫持了来自 192.168.1.40 的tcp 443的流量,修改到了12345端口。

电脑

开启CharlesProxy的Socks服务
Proxy菜单 -> Proxy Settings… -> Proxies
勾选“Enable SOCKS proxy”,Port“8889”,勾选“Enable HTTP proxying over SOCKS”和“Include default HTTP ports(80,443,8080,8443)”。

由于默认状态下,CharlesProxy列表里出现的都是IP,没有域名,所以简单粗暴地对所有的443端口开启SSL proxy。
Proxy菜单 -> SSL Proxy Settings… -> SSL Proxying
直接Add一个 Host=*,Port=443的项目,并启用。用完就关掉。

接下来就是Rewrite的了,在看到流量之前就不用考虑了。
工具在 Tools菜单里就能看到。

另类方法劫持手机流量 by @sskaje: https://sskaje.me/2017/04/hijack-mobile-phone-traffic-using-router-and-charlesproxy/

TCPDUMP Capture Netlink Packets

I’m writing a Wireshark Dissector for IPSET’s protocol. Commands below are to capture netlink packets using tcpdump.

TCPDUMP Capture Netlink Packets by @sskaje: https://sskaje.me/2017/04/tcpdump-capture-netlink-packets/

基于SNIProxy的路由端网络流量定制分发方案

标题感觉很高大上,其实写得乱七八糟。

前序文章:
SNIProxy Bind Outgoing Interface
Build SNIProxy Debian Package for EdgeRouter
Ubnt EdgeRouter Lite 和 EdgeRouter X 上安装使用SNIProxy

不急,上边三篇可能会在本文内提及。

首先,sniproxy不解释了,但是如标题所属,sniproxy的版本不支持我要的功能,所以我就fork然后改了。
具体思路参考上述第一个链接。

接下来,直接进入正题。

按之前的玩法,我使用路由表来控制流量。这是一个很典型,也很正确的做法;但是也是一个很不好用的玩法。
参考文章:Set up OpenVPN Site-to-Site on UBNT EdgeRouter Lite, EdgeOS PPTP VPN客户端配置
PS:我维护了一份自己的路由表,地址在 https://ip.rst.im/blocks/sskaje

为了让定制化程度高一些,我配了一个Socks代理,实际上是在vpn对端配置的,本地路由做了个DNAT,转发过去了。这样我就可以用firefox+foxyproxy实现本地定制化规则。
参考文章:UBNT VPN + Socks5 代理Set up dante-server on Ubuntu

后来考虑到上述用起来麻烦,又趁着回老家的时候,在家里的ac68u merlin上实践了下WPAD,不过没有在自己家里的edgerouter上搞。
参考文章:Setup WPAD on Asus Merlin

此外,还试了一下基于源IP的firewall modify。印象中没单写blog,但是提过和用路由表的方案的优劣。
基本思路是:定义一个源地址的firewall network group;配置protocol static table;在LAN口的防火墙规则里增加modify,根据源地址组强行修改路由表。

从实际经验看,路由表不是最佳选择。
好处不必提,稳定,稳定,稳定。
坏处是,启动、更新慢慢慢。

而且现阶段,大量网站都用了诸如 cloudflare, amazon cloudfront,akamai,fastly之类的CDN服务,单纯按网段切路由,很不现实也很不灵活。
所以趁着需求,改造了一下sniproxy。
用的时间不长,所以暂时没法评估稳定性。

首先,软件部署在路由上。edgerouter lite 和 edgerouter x的包都打好了,1.9.0的固件可以直接装,下载地址在前边三个链接里有。

为了达到我要的目的,条件如下:
1 需要有本地DNS服务器(我的路由上有dnsmasq);
2 需要有稳定的VPN设备(我的是openvpn site2site,设备名vtun0)。
我的路由LAN IP是 192.168.32.1/24,设备eth0。

首先,为当前路由添加一个新的IP(我的是192.168.32.2/24),与默认IP同网段。
这里,命令行操作的时候务必别写错了设备名。其他没什么要注意的。
大致命令如下:

其次,配置好dnsmasq,将需要劫持的域名解析到 192.168.32.2。解析的配置参考下列例子

实际的经验是,不要用 set service dns forwarding options 来设置dnsmasq,自己维护一个配置文件,放在 /config/ 下,link/etc/dnsmasq.d

第三步,安装配置我的版本的sniproxy,假定监听端口分别问 192.168.32.2:3080 和 192.168.32.2:3443,分别用于接收 80端口和443端口的请求。
安装步骤参考最前边的链接。
配置文件参考

最后,配置DNAT,将192.168.32.2:80和192.168.32.2:443分别转到3080和3443,防止80和443的请求到达路由的lighttpd。

基于SNIProxy的路由端网络流量定制分发方案 by @sskaje: https://sskaje.me/2016/11/%e5%9f%ba%e4%ba%8esniproxy%e7%9a%84%e8%b7%af%e7%94%b1%e7%ab%af%e7%bd%91%e7%bb%9c%e6%b5%81%e9%87%8f%e5%ae%9a%e5%88%b6%e5%88%86%e5%8f%91%e6%96%b9%e6%a1%88/

SNIProxy Bind Outgoing Interface

这篇纯技术,没兴趣的别看。

关于需求

最早试图用路由器自带的功能去实现sni检测+自动路由,结果发现edgerouter的dpi没开放太多资料。
再又试图用squid去实现正向代理,绑定上行网络地址或者设备,虽然edgerouter自带squid以实现transparent proxy,但是自带版本SNI检测不支持(新版不知),绑定upstream的地址或者设备也没看到有人说支持。
又考虑过haproxy,但是这个必须自己写backend(似乎可以haproxy + squid,没去实践过,至少haproxy的acl要写好长;而且这个组合里haproxy都可以直接被跳过,反正有DNAT也有DNS劫持)。

从上边的方案思考过程,我觉得应该能看懂我想要什么。

关于实现

选用sniproxy,也算偶然。虽然之前vps上实验sni检测+代理的时候,大概看了眼(但是最后还是选了haproxy)。不过最后选这个的重要原因就是好改 XD
官方github在https://github.com/dlundquist/sniproxy。

先考虑的方案是,通过socket上联时绑定客户端IP。
本身支持上行设置请求的源地址,大致实现代码在 connection.c:

但是经过试验,配置source address后,数据包还是会根据路由上的路由表跳到域名解析IP该走的那个网络。

所以,这个方案是不满足我的要求的。

如果绑定IP不行,那就试试绑定设备。
绑定IP的方案的可行性,很早以前跟同学Windows下讨论一个客户端设计的时候验证过;但是绑定设备的,完全没搞过。
现查。

然后查到了 SO_BINDTODEVICE

SO_BINDTODEVICE
Bind this socket to a particular device like “eth0”, as specified in the passed interface name. If the name is an empty string or the option length is zero, the socket device binding is removed. The passed option is a variable-length null-terminated interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this only works for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(2) there).
Before Linux 3.8, this socket option could be set, but could not retrieved with getsockopt(2). Since Linux 3.8, it is readable. The optlen argument should contain the buffer size available to receive the device name and is recommended to be IFNAMSZ bytes. The real device name length is reported back in the optlen argument.

不过比较麻烦的是,这个只支持IPV4,而且必须使用root。

具体实践在 https://github.com/sskaje/sniproxy
mips(64)/mipsel的deb包已经放在 http://dl.sskaje.me/debian/,供 edgerouter lite/edgerouter x使用,未签名。

具体代码:

还需要说明的是,这个也只能在Linux上用。

关于应用

应用方案,单独写,跟这篇关系没那么大。

SNIProxy Bind Outgoing Interface by @sskaje: https://sskaje.me/2016/11/sniproxy-bind-outgoing-interface/

Incoming search terms: