关于梯子的那些基本知识

image

姿势很多,我们今天主要聊聊与之相关的技术。


透明代理

大多数的软件,打开之后,就会自动的将所有的请求都通过代理转发,这个一般被称之为 透明代理 因为使用者并不需要给应用挨个的配置代理地址。

传统代理如下图

image

一般来说会有一个访问代理服务器,经过代理服务的 NAT 之后的请求,不过麻烦的更多是需要人工配置。

但是透明代理

image

在透明代理的模式下,由于客户端请求数据包的目的地址不是代理服务器,因此需要通过路由和 iptables 规则将客户端的请求发送给代理服务器处理。
首先将代理服务器设置为客户端的缺省网关,以将请求发送到代理服务器。请求路由到代理服务器后,还需要通过 iptables 将请求重定向到代理进程进行处理。可以有两种办法:
1.采用 DNAT 将请求重定向到代理进程,这种方式会修改请求 IP 数据包的目的地址和端口。代理服务器收到客户端请求后,可以通过调用 getsockopt 的 SO_ORIGINAL_DST 参数拿到原始请求的目的地址。
2.采用 TPROXY 来将请求发送到代理进程,这种方式不会修改请求 IP 数据包的目的地址和端口。因此代理服务器可以直接从 socket 中拿到其请求目的地。
采用 TPROXY 模式时,需要路由规则、iptables 和代理进程进行配合。
FROM tproxy(透明代理)

不过具体的实现上不仅仅只有上面说的一些方式,本质上我们需要让系统自动将流量打到代理,让代理自行处理。所以下面介绍一些基本的知识

Netfilter

Linux 使用 Netfilter 来管理网络,Netfilter 模型如下:
image

不过我个人更喜欢这个

image

iptables 使用 table 来组织规则,根据用来做什么类型的判断标准,将规则分为不同 table。例如,如果规则是处理 网络地址转换 的,那会放到 nat table;如果是判断是否允许包继续向前,那可能会放到 filter table

但是从时序上理解,主要还是从链上执行

  • PREROUTING: 由 NF_IP_PRE_ROUTING hook 触发
  • INPUT: 由 NF_IP_LOCAL_IN hook 触发
  • FORWARD: 由 NF_IP_FORWARD hook 触发
  • OUTPUT: 由 NF_IP_LOCAL_OUT hook 触发
  • POSTROUTING: 由 NF_IP_POST_ROUTING hook 触发

这里有个完整的图

image

配置方式

Iptables 的配置方式如下

1
iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]
  • 表名、链名:指定iptables命令所操作的表和链,未指定表名时将默认使用filter表;
  • 管理选项:表示iptables规则的操作方式,比如:插入、增加、删除、查看等;
  • 匹配条件:指定要处理的数据包的特征,不符合指定条件的数据包不处理;
  • 控制类型:指数据包的处理方式,比如:允许accept、拒绝reject、丢弃drop、日志LOG等;
1
2
3
4
5
6
7
8
9
10
11
12
iptables 命令的常用管理选项
-A:在指定链的末尾添加一条新的规则
-D:删除指定链中的某一条规则,可删除指定序号或具体内容
-I:在指定链中插入一条新规则,未指定序号时默认作为第一条规则
-R:修改、替换指定链中的某一条规则,可指定规则序号或具体内容
-L:列出指定链中所有的规则,未指定链名,则列出表中的所有链
-F:清空指定链中所有的规则,未指定链名,则清空表中的所有链
-P:设置指定链的默认策略
-n:使用数字形式显示输出结果
-v:查看规则列表时显示详细的信息
-h:查看命令帮助信息
--line-numbers:查看规则列表时,同时显示规则在链中的顺序号

实践一下

环境准备

我们准备一个 Linux 环境,配置好代理服务,我们使用代理就可以访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ http_proxy="socks://127.0.0.1:1080" https_proxy="socks://127.0.0.1:1080" curl -v www.google.com
* Uses proxy env variable http_proxy == 'socks://127.0.0.1:1080'
* Trying 127.0.0.1:1080...
* Connected to 127.0.0.1 (127.0.0.1) port 1080 (#0)
* SOCKS4 communication to www.google.com:80
* SOCKS4 non-blocking resolve of www.google.com
* SOCKS4 connect to IPv4 31.13.94.49 (locally resolved)
* SOCKS4 request granted.
* Connected to 127.0.0.1 (127.0.0.1) port 1080 (#0)
> GET / HTTP/1.1
> Host: www.google.com
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: https://www.google.com/
< Content-Type: text/plain
< Server: proxygen-bolt
< Date: Sun, 24 Nov 2024 13:37:21 GMT
< Connection: keep-alive
< Content-Length: 0
<
* Connection #0 to host 127.0.0.1 left intact

在开始透明流量之前,我们先要理解,此时的模式是 Proxy 的正向代理,因此单纯的将流量劫持是不生效的,需要先开始代理的透明代理模式

1
sslocal -b "127.0.0.1:60080" --protocol redir -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --tcp-redir "redirect" --udp-redir "tproxy"

这里我们就看到了 60080 的监听了

1
2
3
4
5
6
7
$ netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 localhost:1033 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN
tcp 0 0 localhost:60080 0.0.0.0:* LISTEN
tcp6 0 0 [::]:ssh [::]:* LISTEN

劫持所有流量

1
2
3
4
5
6
iptables -t nat -N Proxy # 新建一个名为 Proxy 的链
iptables -t nat -A Proxy -d 192.168.0.0/16 -j RETURN # 直连 192.168.0.0/16 [局域网地址]
iptables -t nat -A Proxy -d <YOUR_SS_ADDR> -j RETURN # SS 地址放行
iptables -t nat -A Proxy -p tcp -j REDIRECT --to-ports 60080 # 其余流量转发到 60080 端口 (SS)
iptables -t nat -A PREROUTING -p tcp -j Proxy # 对局域网其他设备进行透明代理
iptables -t nat -A OUTPUT -p tcp -j Proxy # 对本机进行透明代理

参考