透明代理(一)

引文

假如我有一部安卓手机,我想把手机上的全部流量打到指定的代理上(即透明代理),代理外接外部的VPN,以达到分散IP出口的目的。

这是这个系列的第一篇文章,本文将简单介绍一下 `SOCKS` 、`iptable` 、`透明代理` 的概念,以及一点小小的实践。

SOCKS

SOCKS是一种网络传输协议,当防火墙后的客户端要访问外部的服务器时,就跟SOCKS代理服务器连接。这个代理服务器控制客户端访问外网的资格,允许的话,就将客户端的请求发往外部的服务器。

SOCKS5协议

参考

rfc:https://tools.ietf.org/html/rfc1928

wikipadia:https://zh.wikipedia.org/wiki/SOCKS

创建与SOCKS5服务器的TCP连接后客户端需要先发送请求来协议版本及认证方式,格式为(以字节为单位):

VER NMETHODS METHODS

111-255

VER是SOCKS版本,这里应该是0x05;

NMETHODS是METHODS部分的长度;

METHODS是客户端支持的认证方式列表,每个方法占1字节。当前的定义是:

0x00 不需要认证

0x01 GSSAPI

0x02 用户名、密码认证

0x03 - 0x7F由IANA分配(保留)

0x80 - 0xFE为私人方法保留

0xFF 无可接受的方法

服务器从客户端提供的方法中选择一个并通过以下消息通知客户端(以字节为单位):

VERMETHOD

11

VER是SOCKS版本,这里应该是0x05;

METHOD是服务端选中的方法。如果返回0xFF表示没有一个认证方法被选中,客户端需要关闭连接。

之后客户端和服务端根据选定的认证方式执行对应的认证。

认证结束后客户端就可以发送请求信息。如果认证方法有特殊封装要求,请求必须按照方法所定义的方式进行封装。

SOCKS5请求格式(以字节为单位):

VERCMDRSVATYPDST.ADDRDST.PORT

110x001动态2

VER是SOCKS版本,这里应该是0x05;

CMD是SOCK的命令码

0x01表示CONNECT请求

0x02表示BIND请求

0x03表示UDP转发

RSV 0x00,保留

ATYP DST.ADDR类型

0x01 IPv4地址,DST.ADDR部分4字节长度

0x03域名,DST ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有\0结尾。

0x04 IPv6地址,16个字节长度。

DST.ADDR 目的地址

DST.PORT 网络字节序表示的目的端口

服务器按以下格式回应客户端的请求(以字节为单位):

VERREPRSVATYPBND.ADDRBND.PORT

110x001动态2

VER是SOCKS版本,这里应该是0x05;

REP应答字段

0x00表示成功

0x01普通SOCKS服务器连接失败

0x02现有规则不允许连接

0x03网络不可达

0x04主机不可达

0x05连接被拒

0x06 TTL超时

0x07不支持的命令

0x08不支持的地址类型

0x09 - 0xFF未定义

RSV 0x00,保留

ATYP BND.ADDR类型

0x01 IPv4地址,DST.ADDR部分4字节长度

0x03域名,DST.ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有\0结尾。

0x04 IPv6地址,16个字节长度。

BND.ADDR 服务器绑定的地址

BND.PORT 网络字节序表示的服务器绑定的端口

SOCKS5 用户名密码认证方式

在客户端、服务端协商使用用户名密码认证后,客户端发出用户名密码,格式为(以字节为单位):

鉴定协议版本用户名长度用户名密码长度密码

11动态1动态

鉴定协议版本目前为 0x01 。

服务器鉴定后发出如下回应:

鉴定协议版本鉴定状态

11

其中鉴定状态 0x00 表示成功,0x01 表示失败。

iptable

参考

wikipadia:https://zh.wikipedia.org/wiki/Iptables

Archlinux: https://wiki.archlinux.org/index.php/Iptables_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

iptables 是一个配置 Linux 内核 防火墙 的命令行工具,是 netfilter 项目的一部分。术语 iptables 也经常代指该内核级防火墙。iptables 用于 ipv4,ip6tables 用于 ipv6。

iptables 可以检测、修改、转发、重定向和丢弃 IPv4 数据包。过滤 IPv4 数据包的代码已经内置于内核中,并且按照不同的目的被组织成 表 的集合。表 由一组预先定义的 链 组成,链 包含遍历顺序规则。每一条规则包含一个谓词的潜在匹配和相应的动作(称为 目标),如果谓词为真,该动作会被执行。也就是说条件匹配。iptables 是用户工具,允许用户使用 链 和 规则。

透明代理

透明代理可以是通过配置iptable(设置防火墙规则),将电脑上的网络请求`全部` 、`自动` 代理出去。

下面,我用 `redsocks` 做一下实践。

参考

http://darkk.net.ru/redsocks/

https://github.com/darkk/redsocks

redsocks只是一个TCP-to-proxy的转向器,支持把流量打到SSH、SOCKS5等

有几个步骤:

0,开启redsocks

```bash

sudo apt-get install iptables git-core libevent-1.4-2 libevent-dev

git clone http://github.com/darkk/redsocks.git

cd redsocks

make

vim redsocks.conf

```

redsocks.conf

```

base{

log_debug = on;

log_info = on;

log = "file:/tmp/reddi.log";

daemon = on;

redirector = iptables;

}

redsocks {

local_ip = 127.0.0.1;

local_port = 20182;

ip = 127.0.0.1;

port = 20183;

type = socks5;

}

```

```bash

./redsocks -c redsocks.conf

```

1,把设置iptable的规则,把流量打到redsocks上

```bash

# 创建规则

root# iptables -t nat -N REDSOCKS

# 忽略内网流量

root# iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN

root# iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN

root# iptables -t nat -A REDSOCKS -d 100.64.0.0/10 -j RETURN

root# iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN

root# iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN

root# iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN

root# iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN

root# iptables -t nat -A REDSOCKS -d 198.18.0.0/15 -j RETURN

root# iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN

root# iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

# 外网流量

root# iptables -t nat -A REDSOCKS -p tcp -o eth0 -j DNAT --to 127.0.0.1:20182

root# iptables -t nat -A OUTPUT -p tcp -j REDSOCKS

```

ps:iptable关机时所有配置会丢失。可以将当前配置保存到文件

```bash

# 保存

root# iptables-save > proxy.iptablesv

# 恢复

root# iptables-restore proxy.iptables

```

2.1,在20183端口建立ssh通道

`Local`

```bash

```

检查

`ServerB`

```bash

watch -n 1 -d "netstat -an grep 118.89.53.151"

```

`Local`

```bash

wget 118.89.53.151

```

result(`ServerB`)

```

Every 1.0s: netstat -an grep 118.89.53.151 Wed Feb 28 15:41:05 2018

tcp 0 0 192.168.0.92:44426 118.89.53.151:443 TIME_WAIT

tcp 0 0 192.168.0.92:46026 118.89.53.151:80 TIME_WAIT

```

可以看到,在本地执行的`wget` 在ServerB上能看到建立的端口,流量就这样自动通过ssh出去了。

这里我们已经用iptable、redsocks、ssh做了一层透明代理。

2.2,设置redsocks的出口为socks5

a,部署一个简单的 socks server

`python2.7` `ServerB:192.168.0.92`

```

git clone https://github.com/fengyouchao/pysocks.git

cd pysocks

python socks5.py start

```

`ServerB`

```bash

# 关闭

python socks5.py stop

```

b,修改步骤0中的`redsocks.conf`

改成:

`Local`

```

base{

log_debug = on;

log_info = on;

log = "file:/tmp/reddi.log";

daemon = on;

redirector = iptables;

}

redsocks {

local_ip = 127.0.0.1;

local_port = 20182;

ip = 192.168.0.92;

port = 1080;

type = socks5;

}

```

```bash

ps aux grep redsocks

# 24588

kill -9 24588

./redsocks -c redsocks.conf

```

c,检查

`ServerB`

```bash

watch -n 1 -d "netstat -an grep 118.89.53.151"

```

`Local`

```bash

wget 118.89.53.151

```

result(`ServerB`)

```

Every 1.0s: netstat -an grep 118.89.53.151 Wed Feb 28 15:41:05 2018

tcp 0 0 192.168.0.92:44426 118.89.53.151:443 TIME_WAIT

tcp 0 0 192.168.0.92:46026 118.89.53.151:80 TIME_WAIT

```

这样过了一轮之后,概念也熟悉了,本机的流量就可以想怎么发就怎么发了。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180228G0U83I00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券