Total Pageviews

Thursday, 18 February 2016

redsocks教程

严格意义上来说,proxychains不算自动的全局代理,那么有没有像Proxifier那样的程序-开了之后,自动让所有启动的程序都走系统代理呢?答案就是redsocks。
首先安装Ubuntu编译环境和必要的库:
sudo apt-get install autoconf automake libtool libevent-dev g++
下载源代码,然后编译安装:
./mkauto.sh
cp redsocks /usr/local/bin/
配置文件为:
base {
// debug: connection progress & client list on SIGUSR1
log_debug = off;
// info: start and end of client session
log_info = off;
/* possible `log’ values are:
* stderr
* file:/path/to/file
* syslog:FACILITY facility is any of "daemon", "local0"…"local7"
*/
log = "file:/dev/null";
// log = stderr;
// log = "file:/path/to/file";
// log = "syslog:local7";
// detach from console
daemon = on;
/* Change uid, gid and root directory, these options require root
* privilegies on startup.
* Note, your chroot may requre /etc/localtime if you write log to syslog.
* Log is opened before chroot & uid changing.
*/
// user = nobody;
// group = nobody;
// chroot = "/var/chroot";
/* possible `redirector’ values are:
* iptables – for Linux
* ipf – for FreeBSD
* pf – for OpenBSD
* generic – some generic redirector that MAY work
*/
redirector = iptables;
}
redsocks {
/* `local_ip’ defaults to 127.0.0.1 for security reasons,
* use 0.0.0.0 if you want to listen on every interface.
* `local_*’ are used as port to redirect to.
*/
local_ip = 127.0.0.1;
local_port = 12345;
// `ip’ and `port’ are IP and tcp-port of proxy-server
ip = 127.0.0.1;
port = 7070;
// known types: socks4, socks5, http-connect, http-relay
type = socks5;
// login = "foobar";
// password = "baz";
}
redudp {
// `local_ip’ should not be 0.0.0.0 as it’s also used for outgoing
// packets that are sent as replies – and it should be fixed
// if we want NAT to work properly.
local_ip = 127.0.0.1;
local_port = 10053;
// `ip’ and `port’ of socks5 proxy server.
ip = 10.0.0.1;
port = 1080;
login = username;
password = pazzw0rd;
// kernel does not give us this information, so we have to duplicate it
// in both iptables rules and configuration file. By the way, you can
// set `local_ip’ to 127.45.67.89 if you need more than 65535 ports to
// forward
// This limitation may be relaxed in future versions using contrack-tools.
dest_ip = 8.8.8.8;
dest_port = 53;
udp_timeout = 30;
udp_timeout_stream = 180;
}
dnstc {
// fake and really dumb DNS server that returns "truncated answer" to
// every query via UDP, RFC-compliant resolver should repeat same query
// via TCP in this case.
local_ip = 127.0.0.1;
local_port = 5300;
}
// you can add more `redsocks’ and `redudp’ sections if you need.
这里的配置没有配置udp的代理部分,只是配置了tcp即redsocks部分。监听端口是12345。日志关闭了,因为好像我下载的当前版本无论怎么样都产生一堆调试日志,不知道以后会不会修复这点。
启动关闭脚本redsocks.sh为(via):
#! /bin/bash
SSHHOST=creke
SSHPORT=22
SSHUSR=creke
SSHPWD=creke
SSHDAEMON=/usr/local/bin/plink
SSHPIDFILE=/var/run/sshtunnel.pid
start_ssh()
{
    echo "Start SSH Tunnel Daemon: "
    start-stop-daemon -b -q -m -p $SSHPIDFILE –exec $SSHDAEMON -S \
    — -N -D 127.0.0.1:7070 -P $SSHPORT -pw $SSHPWD $SSHUSR@$SSHHOST
    echo "SSH Tunnel Daemon Started."
}
stop_ssh()
{
    #ps aux|grep "ssh -NfD 1234"|awk ‘{print $2}’|xargs kill
    if [ -f $SSHPIDFILE ]; then
    PID=$(cat $SSHPIDFILE)
    kill $PID
    while [ -d /proc/$PID ];
    do
    sleep 1
    done
    fi
    rm -rf $SSHPIDFILE
    echo "SSH Tunnel Daemon Stoped."
}
case "$1" in
  start)
    start_ssh
    cd /usr/local/redsocks
    if [ -e redsocks.log ] ; then
      rm redsocks.log
    fi
    ./redsocks -p /usr/local/redsocks/redsocks.pid #set daemon = on in config file
    # start redirection
    # iptables -t nat -A OUTPUT -p tcp –dport 80 -j REDIRECT –to 12345
    # iptables -t nat -A OUTPUT -p tcp –dport 443 -j REDIRECT –to 12345
    # Create new chain
    iptables -t nat -N REDSOCKS
    # Ignore LANs and some other reserved addresses.
    iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
    iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
    iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
    iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
    iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
    # Anything else should be redirected to port 12345
    iptables -t nat -A REDSOCKS -p tcp -j REDIRECT –to-ports 12345
    # Any tcp connection should be redirected.
    iptables -t nat -A OUTPUT -p tcp -j REDSOCKS
    ;;
  stop)
    stop_ssh
    cd /usr/local/redsocks
    if [ -e redsocks.pid ]; then
      kill `cat redsocks.pid`
      rm redsocks.pid
    else
      echo already killed, anyway, I will try killall
      killall -9 redsocks
    fi
    # stop redirection
    iptables -t nat -F OUTPUT
    iptables -t nat -F REDSOCKS
    iptables -t nat -X REDSOCKS
    ;;
  start_ssh)
    start_ssh
    ;;
  stop_ssh)
    stop_ssh
    ;;
  clean_dns)
    # iptables -A INPUT -p udp –sport 53 -m state –state ESTABLISHED -m you-know-who -j DROP -m comment –comment "drop you-know-who dns hijacks"
    echo this function not finished
    ;;
  *)
    echo "Usage: redsocks start|stop|start_ssh|stop_ssh|clean_dns" >&2
    exit 3
    ;;
esac
iptables的规则是让所有的TCP包都发送到redsocks监听的端口12345。本脚本还整合了ssh的daemon启动,使用start-stop-daemon来实现。
启动和关闭:
将启动关闭脚本中的开头的几个变量配置好
启动命令:sudo ./redsocks.sh start
关闭命令:sudo ./redsocks.sh stop

项目地址:https://github.com/darkk/redsocks,
http://darkk.net.ru/redsocks
https://github.com/semigodking/redsocks
--------------

socks proxy的可路由化

与VPN相比,SSH动态转发只是一个SOCKS代 理,不如VPN那种建立一个点到点连接的方式处理方便。首先,VPN连接可以在路由表中配置,不需要软件支持和显式指定;其次,因为VPN的“连接”性 质,用户可以灵活地配置流量的走向,比如访问Chinternet用原本的连接,访问Internet用VPN连接。当然,SOCKS代理的优势也是显而 易见的,只要有一个SSH账号,即可建立隧道,一般来说,要比VPN的花费要少。在后续的文章中,Li哥将介绍在普通的无SSH支持的PHP主机上实现穿 透代理。
本文的目的是将SOCKS代理透明化和可路由化
它的应用场景如下:
1. 透明代理,即可不指定代理而自动使用SOCKS代理转发。换句话说,把代理配置在了应用层以下
2. 共享代理,即把只能本地访问的SOCKS代理(SSH隧道)转换成可共享的。也就是不透露SSH账号且只建立一次隧道,即可供多人使用。
3. 转发规则自定义,即可将分组分类(比如按目的地址分类)并配置转发。
4. 其它。

redsocks

用过squid的读者应该知道,用squid和iptables来实现上面的需求很简单,首先在服务端squid.conf中的port选项后增加“transparent”字段,然后将相应请求用iptables redirect到端口即可。
iptables -t nat -A PREROUTING -p tcp --dport 80 -d xx.xx.xx.xx -j REDIRECT --to-port 3128
但SSH建立的socks代理不具备这样的功能,只能通过第三方的软件来扩展。 本文介绍一款名为redsocks的软件。redsocks是我目前发现在这方面最好的软件。
redsocks可以在http://darkk.net.ru/redsocks/下载,也可在此下载http://blog.lilinux.net/attachment/darkk-redsocks-a37aa7a.zip
redsocks的官方说明
This tool allows you to redirect any TCP connection to SOCKS or HTTPS
proxy using your firewall, so redirection is system-wide.

Why is that useful? I can suggest following reasons:
* you use tor[1] and don't want any TCP connection to leak.
* you use DVB ISP and this ISP provides internet connectivity with some
  special daemon that may be also called "Internet accelerator" and this
  accelerator acts as proxy. Globax[2] is example of such an accelerator.

Linux/iptables, OpenBSD/pf and FreeBSD/ipfw are supported.
Linux/iptables is well-tested, other implementations may have bugs,
your bugreports are welcome.

Transocks[3] is alike project but it has noticable performance penality.

Transsocks_ev[4] is alike project too, but it has no HTTPS-proxy support
and does not support authentication.

redsocks的安装

1. 安装libevent组件

libevent的官方页面:http://www.monkey.org/~provos/libevent/
值得注意的是,发行版源仓库中的libevent一般的版本较低,在编译redsocks时会失败。Debian/Ubuntu所需的libevent可以从此下载:http://ftp.de.debian.org/debian/pool/main/libe/libevent/
本站也提供libevent的deb包下载:http://blog.lilinux.net/attachment/libevent.zip

2. 编译redsocks

解压、make
这个应该不需要详细介绍了

3. 编辑配置文件

在redsocks目录下建立配置文件redsocks.conf。内容如下(因为配置文件注释与C++相同,故用C++代码风格加亮)
base {
 log_debug = on;
 log_info = on;
  //日志文件,调试时可指定为标准错误"stderr"
 log = "file:/home/lige/soft/redsocks/socks.log";

 // 是否以后台模式运行
 daemon = on
 redirector = iptables;
}

redsocks {
         //local_ip设置为0.0.0.0则可共享,设备为127.0.0.1则只能在本机使用
 local_ip = 0.0.0.0
 local_port = 12345;

 // 本来有的代理的IP和端口,可能是由ssh -D指定的
 ip = 127.0.0.1;
 port = 1080;

 // known types: socks4, socks5, http-connect, http-relay
 type = socks5;
}

4. iptables策略

新建一个脚本tp-socks.sh,用来运行redsocks和生成iptables策略
脚本摘自przemoc.net
#!/bin/sh

# iptables路径
IPTABLES="/usr/local/sbin/iptables"

# redsocks路径
REDSOCKS_DIR="/home/lili/soft/redsocks"
REDSOCKS="$REDSOCKS_DIR/redsocks"

# 配置文件中指定的端口
REDSOCKS_PORT="12345"

# socks代理IP和端口
SOCKS_HOST="127.0.0.1"
SOCKS_PORT="1080"

# 运行redsocks
if [ "$USER" != "root" ]; then
 echo -n 'Restarting redsocks... '
 pkill -U $USER redsocks 2>/dev/null
 sleep 1
 cd $REDSOCKS_DIR && $REDSOCKS
 if [ $? -eq 0 ]; then
  echo Done
 else
  echo Error
 fi
 exit 0;
elif [ "$1" != "iptables" ]; then
 exit 0
fi

$IPTABLES -t nat -D PREROUTING -p tcp -j REDSOCKS_FILTER 2>/dev/null
$IPTABLES -t nat -D OUTPUT     -p tcp -j REDSOCKS_FILTER 2>/dev/null
$IPTABLES -t nat -F REDSOCKS_FILTER 2>/dev/null
$IPTABLES -t nat -X REDSOCKS_FILTER 2>/dev/null
$IPTABLES -t nat -F REDSOCKS 2>/dev/null
$IPTABLES -t nat -X REDSOCKS 2>/dev/null

# Create our own chain
$IPTABLES -t nat -N REDSOCKS
$IPTABLES -t nat -N REDSOCKS_FILTER

# Do not try to redirect local traffic
$IPTABLES -t nat -I REDSOCKS_FILTER -o lo -j RETURN

### 以下是iptables策略配置,包括白名单和黑名单,默认开启白名单
### 你应该至少修改一行配置,也很简单

# Redirect only specified addresses and do not try redirect other traffic. (whitelist option)
# 白名单选项:只重定向指定的分组到SOCKS代理,其它的都按默认路由转发
$IPTABLES -t nat -A REDSOCKS_FILTER -m iprange --dst-range 192.168.0.10-192.168.0.30 -j REDSOCKS
$IPTABLES -t nat -A REDSOCKS_FILTER -d 126.0.0.0/8 -j REDSOCKS
$IPTABLES -t nat -A REDSOCKS_FILTER -j RETURN

## Do not redirect LAN traffic and some other reserved addresses. (blacklist option)
# 黑名单选项:指定的分组通过默认路由转发,其它的都转向SOCKS代理
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 0.0.0.0/8 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 10.0.0.0/8 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 127.0.0.0/8 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 169.254.0.0/16 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 172.16.0.0/12 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 192.168.0.0/16 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 224.0.0.0/4 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -d 240.0.0.0/4 -j RETURN
#$IPTABLES -t nat -A REDSOCKS_FILTER -j REDSOCKS

## Do not redirect traffic for the SOCKS-Server
## Not needed if server is not on a whitelist or is already blacklisted.
# 不转发。实际没什么意义,不需要SOCKS时只需要清空nat表即可
#$IPTABLES -t nat -I REDSOCKS -p tcp -d $SOCKS_HOST --dport $SOCKS_PORT -j RETURN

# Redirect all traffic that gets to the end of our chain
# 将未指定的转发到SOCKS代理,实际上不会用到
$IPTABLES -t nat -A REDSOCKS   -p tcp -j REDIRECT --to-port $REDSOCKS_PORT

## Filter all traffic from the own host
# 将分组转到REDSOCKS_FILTER,以保证对分组的区分处理,作用于本机
## BE CAREFULL HERE IF THE SOCKS-SERVER RUNS ON THIS MACHINE
$IPTABLES -t nat -A OUTPUT     -p tcp -j REDSOCKS_FILTER

# Filter all traffic that is routed over this host
# 将分组转到REDSOCKS_FILTER,以保证对分组的区分处理,作用于子网
$IPTABLES -t nat -A PREROUTING -p tcp -j REDSOCKS_FILTER

echo IPtables reconfigured.
一般来说,只需要增加白名单里的条目即可。

5. 运行
打开redsocks

./tp-socks.sh
加载iptables策略
sudo ./tp-socks.sh iptables

实例:自动使用SOCKS代理访问某微博网站

这事儿不能说太细,仅供参考
把这个网站的IP添加到脚本的白名单策略中
$IPTABLES -t nat -A REDSOCKS_FILTER -d xx.xx.xx.xx -j REDSOCKS
但是由于DNS污染,本地解析的IP可能是错误的,而且socks代理的远端DNS解析的方法不适用。解决的办法有2种:
(1) 将DNS解析,即目的端口为53的分组转发到SOCKS代理
(2) 在远程计算机上解析IP后,在/etc/hosts中将IP和站点绑定
经过以上步骤,站点成功打开。值得注意的是,这种方法应用于网关时,子网中的主机可以不用更改任何选项访问此站点。这就是透明化的好处之一。
------------------

redsocks - 代理所有流量 - use redsocks to proxy all traffic

幸好我们还有 redsocks,它可以代理所有流量到指定端口。

首先,我们需要安装 redsocks ,这个请自行解决啊,我使用 Manjaro,打开 添加/删除软件 搜索下就OK了,下面,我们配置它。

sudo vim /etc/redsocks.conf

base {
// debug: connection progress & client list on SIGUSR1
log_debug = off;
// info: start and end of client session
log_info = off;
/* possible `log' values are:
* stderr
* "file:/path/to/file"
* syslog:FACILITY facility is any of "daemon", "local0"..."local7"
*/
// log = stderr;
// log = "file:/path/to/file";
log = "syslog:daemon";
// detach from console
daemon = on;
/* Change uid, gid and root directory, these options require root
* privilegies on startup.
* Note, your chroot may requre /etc/localtime if you write log to syslog.
* Log is opened before chroot & uid changing.
*/
user = redsocks;
group = redsocks;
// chroot = "/var/chroot";
/* possible `redirector' values are:
* iptables - for Linux
* ipf - for FreeBSD
* pf - for OpenBSD
* generic - some generic redirector that MAY work
*/
redirector = iptables;
}
redsocks {
/* `local_ip' defaults to 127.0.0.1 for security reasons,
* use 0.0.0.0 if you want to listen on every interface.
* `local_*' are used as port to redirect to.
*/
local_ip = 127.0.0.1;
local_port = 31338;
// listen() queue length. Default value is SOMAXCONN and it should be
// good enough for most of us.
// listenq = 128; // SOMAXCONN equals 128 on my Linux box.
// `max_accept_backoff` is a delay to retry `accept()` after accept
// failure (e.g. due to lack of file descriptors). It's measured in
// milliseconds and maximal value is 65535. `min_accept_backoff` is
// used as initial backoff value and as a damper for `accept() after
// close()` logic.
// min_accept_backoff = 100;
// max_accept_backoff = 60000;
// `ip' and `port' are IP and tcp-port of proxy-server
// You can also use hostname instead of IP, only one (random)
// address of multihomed host will be used.
ip = 127.0.0.1;
port = 1080;
// known types: socks4, socks5, http-connect, http-relay
type = socks5;
// login = "foobar";
// password = "baz";
}
redudp {
// `local_ip' should not be 0.0.0.0 as it's also used for outgoing
// packets that are sent as replies - and it should be fixed
// if we want NAT to work properly.
local_ip = 127.0.0.1;
local_port = 10053;
// `ip' and `port' of socks5 proxy server.
ip = 127.0.0.1;
port = 1080;
// login = username;
// password = pazzw0rd;
// kernel does not give us this information, so we have to duplicate it
// in both iptables rules and configuration file. By the way, you can
// set `local_ip' to 127.45.67.89 if you need more than 65535 ports to
// forward ;-)
// This limitation may be relaxed in future versions using contrack-tools.
dest_ip = 8.8.8.8;
dest_port = 53;
udp_timeout = 30;
udp_timeout_stream = 180;
}
dnstc {
// fake and really dumb DNS server that returns "truncated answer" to
// every query via UDP, RFC-compliant resolver should repeat same query
// via TCP in this case.
local_ip = 127.0.0.1;
local_port = 5300;
}
// you can add more `redsocks' and `redudp' sections if you need.

主要修改 redsocks 节点下面的 ip、port、port 以及 redudp 节点下面的 ip 和 port,然后配置信息就OK了,但是还需要配置 iptables 规则,以下是我的规则:

1、proxy

sudo iptables -t nat -A OUTPUT -d xxx.xxx.xxx.xxx -j RETURN
sudo iptables -t nat -A OUTPUT -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A OUTPUT -d 172.16.0.0/16 -j RETURN
sudo iptables -t nat -A OUTPUT -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A OUTPUT -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 31338

这里注意两点,第一行的 xxx.xxx.xxx.xxx 改为你代理服务器的ip,即 shadowsocks 服务器的 ip,保证这个 ip 不被代理,否则死循环了,最后一行的 31338 需要和 redsocks 节点下面的 local_port 一致。你可以将以上规则保存为 proxy 并保存到 /usr/local/bin/目录下面,然后 sudo chmod a+x /usr/local/bin/proxy 之后就可以通过 proxy 来设置为全局代理了。那么,如何取消呢?

2、del_proxy

#/bin/bash
sudo iptables -t nat -D OUTPUT 6
sudo iptables -t nat -D OUTPUT 5
sudo iptables -t nat -D OUTPUT 4
sudo iptables -t nat -D OUTPUT 3
sudo iptables -t nat -D OUTPUT 2
sudo iptables -t nat -D OUTPUT 1

同样的,保存到 /usr/local/bin/ 目录下面,并 sudo chmod a+x /usr/local/bin/del_proxy 之后可以通过 del_proxy 来取消全局代理了。但是记得 sudo systemctl start redsocks 以及 sudo systemctl enable redsocks 哦!

---------------------------


socks5 代理转发

由于我们VPS上部署的是一个 socks5 代理,相应的我们需要一个 socks5 的客户端。寻寻觅觅,终于让我找到了:redsocks

redsocks – transparent TCP-to-proxy redirector

This tool allows you to redirect any TCP connection to SOCKS or HTTPS proxy using your firewall, so redirection may be system-wide or network-wide.

详细的功能与说明可以在 Github 上查看,我们直接把它 git clone 下来:

由于编译需要依赖到 libevent,我们先安装一下:

然后就可以开始编译 redsocks:

注意:

  • 虽然我们也可以直接用 github 上 release 的版本,不过尽量使用最新的代码避免一些bug;
  • 之前在 OpenWrt 上测试,无奈默认的 ipk 版本是 0.4 ,bug比较多无法正常使用,而自己也不想折腾着去编译 openwrt 版本的 ipk,故放弃了;

配置文件也比较简单,参考目录下的 redsocks.conf.example,主要修改:

然后就可以开始运行:

设置 iptables

参考官方的示例,添加 iptables 规则:

这时候,如果我们手机连接上这个 wifi 热点,那么所有的请求流量都会转发到 redsocks,再转发到我们的 socks5 代理服务器。

DNS 污染

通过上面的配置之后,虽然流量已经走 socks5 代理服务器了,然而我们很大概率会发现 google 仍然打不开。

What the f**k?(黑人问号)

仔细观察后我们便发现了,redsocks 虽然转发了流量,但是在 socks5代理服务器的日志中请求的 ip 却似乎有点问题,也就是说本地的 DNS 域名解析存在猫腻。

这便是所谓的 DNS污染,又称DNS投毒(总有刁民想害朕系列……)

对于DNS污染的问题,我们可以通过自建DNS服务器来解决,网上也有比较多的文章介绍,这里便不再重复了。需要注意的是,如果自建DNS服务器,不能使用境外的VPS,否则经过GFW的数据包回来之后大概率又中毒了。

不过,在这里我们可以更加简单地解决这个问题,因为我们树莓派搭建wifi热点的时候,使用的是 dnsmasq,它本身就是一个DNS服务器,所以我们可以直接配置 ChinaDNS 来解决。

ChinaDNS

从 github 下载它的 release 源码,然后解压并编译:

然后我们需要更新一下 chnroute,获取国内的ip地址段。如果通过 114 DNS(114.114.114.114)解析后得到的是国内ip,则可直接使用;否则应该使用OpenDNS(208.67.222.222:443)解析的结果:

然后运行 chinadns(这里我们将本地DNS服务监听在15353,避免跟dnsmasq冲突):

然后修改一下 dsnmasq 的配置:

然后重启一下 dnsmasq:

至此,我们应该就可以成功 google 啦(撒花~

区分国内外流量

虽然我们已经成功达到了最开始的目标,不过目前看来还有一点小小的遗憾:连上这个wifi热点之后,所有的流量都会经过 socks5 代理。这样子访问国内的网站却反而变慢了,毕竟出国旅游回来绕了一大圈啊!

这个问题可以通过 iptables 来解决,我们前面已经获取到国内的ip地址段 chnroute.txt,直接全部添加到 iptables :

这下子终于完美解决了.

------------------------------

WiFi分享ShadowSocks和同事一起全局科学上网

平时使用shadowsocks或SSH科学上网的时候,感觉速度和稳定性和速度比VPN强不少,但是独乐乐不如众乐乐,如何把我连上ss的电脑做成热点,通过wifi分享给周围其他的人呢?又如何将ss变成一个全局的代理,而不仅仅限于浏览器和少数几个支持代理的软件呢?

做此项研究的起因是公司的一个同事需要翻墙做开发,于是我把ss通过Privoxy转换成http代理爽快的给她用了,但是她反映没什么作用,我看了一下才知道,她在电脑里部署了一个apache服务器用来运行php服务,php程序中有一个耗时操作是链接远在新加坡的MYSQL服务器获取数据,但是该MYSQL服务器被墙了访问很慢,于是php就卡住了,需要想办法让apache服务也翻出墙去,而apache并没有设置代理的相关选项。

如果有一个wifi,链接上该wifi以后电脑里的全部程序都实现了Shadowsocks翻墙,不需要配置这配置那设置各种代理,那岂不是效率高得多,于是从这个出发点开始,我开始用手上的Shadowsocks代理和Ubuntu电脑制作一个可以翻墙的笔记本PC路由器。

 

大体的实现思路:

我的Ubuntu笔记本有两块网卡,一块插网线的有线网卡,一块WIFI无线网卡,用Ubuntu系统自带的功能将无线网卡做成一个热点,然后该无线网卡以有线网卡为网关,所有流量流经有线网卡,当有设备通过WIFI链接上我无线网卡分享出的热点后,所有的流量经过iptables的端口转发后发送给redsocks,再经redsocks发送给Shadowsocks的客户端,最后将流量发送给远程代理服务器,这样无线网卡就变成了一个透明代理,所有通过我电脑分享WIFI上网的设备都实现了全局代理。

 

所需要的设备和软件:

Ubuntu设备一台,据备无线网卡和有线网卡(我用的是一台普通的ThinkPad笔记本)。

一个Shadowsocks帐号(一般十块钱左右一月,网上很多卖的)。

Shadowsocks 客户端

redsocks服务(Ubuntu直接使用apt-get指令安装即可)

 

部署步骤

第一步:安装Shadowsocks客户端

这个方面网上有很多文章介绍,这里就不多说了,总之需要在本机开启一个socks5代理的端口,如果比如127.0.0.1:1080。

(ps:如果要分享给区域网其他用户使用这个端口,就配置成局域网地址:1080比如192.168.1.81:1080)

因为Ubuntu上命令行的Shadowsocks,也就是通过apt-get install sslocal安装的Shadowsocks版本太低,不支持RC4-MD5加密方法,于是我这里用的是图形界面的Shadowsocks-Qt5

(ps:图形界面的Shadowsocks-Qt5稳定性不强,经常请求数一多和流量一高的时候就崩溃,所以我之后又用了另一台Windows电脑开启的SS客户端,Windows版本的Shadowsocks客户端稳定性非常强,我用的时候几乎没有掉过线)。

大体的配置如下-


注:为了防止代理服务器DNS解析出问题,上面的“服务器地址”推荐直接使用IP地址,而不是域名。

 

第二步:部署redsocks服务

redsocks是非常好用的代理软件,用于把普通的tcp流量转换成socks5协议的流量,是这个实现中的关键。

部署起来也不麻烦,首先通过下面的指令进行安装

sudo apt-get update

sudo apt-get install redsocks

然后修改redsocks的配置文件 /etc/redsocks.conf,如下

base {  

// debug: connection progress & client list on SIGUSR1  

log_debug = off;  

// info: start and end of client session  

log_info = on;  

/* possible `log' values are: 

*   stderr 

*  "file:/path/to/file" 

*   syslog:FACILITY  facility is any of"daemon","local0"..."local7" 

*/  

log ="syslog:daemon";  

// detach from console  

daemon = on;  

/* Change uid, gid and root directory, these options require root 

* privilegies on startup. 

* Note, your chroot may requre /etc/localtime if you write log to syslog. 

* Log is opened before chroot & uid changing. 

*/  

user = redsocks;  

group = redsocks;  

// chroot ="/var/chroot";  

/* possible `redirector' values are: 

*   iptables   - for Linux 

*   ipf        - for FreeBSD 

*   pf         - for OpenBSD 

*   generic    - some generic redirector that MAY work 

*/  

redirector = iptables;  

}  

redsocks {  

/* `local_ip' defaults to 127.0.0.1 for security reasons, 

* use 0.0.0.0 if you want to listen on every interface. 

* `local_*' are used as port to redirect to. 

*/  

local_ip = 0.0.0.0;//本地监听的ip地址和端口,一般默认即可  

local_port = 12345;  

// `ip' and `port' are IP and tcp-port of proxy-server  

// You can also use hostname instead of IP, only one (random)  

// address of multihomed host will be used.  

ip = 127.0.0.1;//Shadowsocks 客户端提供的socks5代理端口  

port = 1080;  

// known types: socks4, socks5, http-connect, http-relay  

type = socks5;  

// login ="foobar";//使用Shadowsocks客户端一般不需要用户名和密码  

// password ="baz";  

}  

redudp  

dnstc

然后重启redsocks服务

$ sudo service redsocks start

 

第三步:也是最容易出错的一步了,就是使用iptables配置相关路由协议

我这里把我配置的贴出来

//避免局域网回路  

sudo iptables -t nat -A PREROUTING -d 127.0.0.0/24 -j RETURN   

sudo iptables -t nat -A PREROUTING -d 192.168.0.0/16 -j RETURN  

//让发给其他设备的数据包顺利通过,下面的10.42.0.0/16是连接了Ubuntu热点的设备的ip地址段  

sudo iptables -t nat -A PREROUTING -d 10.42.0.0/16 -j RETURN  

//将其他的数据包,也就是其他设备访问网络的数据包全部转发到redsocks的服务端口  

sudo iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 12345  

//配置好上面的路由规则就可以实现所有连接热点的设备自动翻墙了,但是DNS解析还是在墙内解析,会碰到DNS污染无法访问facebook等网站,所以下面将DNS请求包也转发至SS  

//避免局域网回路  

sudo iptables -t nat -A OUTPUT -d 127.0.0.0/24 -j RETURN  

sudo iptables -t nat -A OUTPUT -d 192.168.0.0/16 -j RETURN  

//让发给其他设备的数据包顺利通过,下面的10.42.0.0/16是连接了Ubuntu热点的设备的ip地址段  

sudo iptables -t nat -A OUTPUT -d 10.42.0.0/16 -j RETURN  

//放行发送给SS服务器的数据包  

sudo iptables -t nat -A OUTPUT -d ShadowSocks代理服务器的远程IP -j RETURN  

//将UDP的DNS解析请求通过redsocks转换成tcp的DNS请求  

sudo iptables -t nat -A OUTPUT -p udp -j REDIRECT --to-ports 5300  

//将TCP的DNS请求通过shadowsocks发送给SS客户端进行远程墙外解析  

sudo iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 12345  

这里不得不说一下,在设置了上面的PREROUTING规则之后,连上笔记本分享wifi的设备就已经把所有的tcp流量走了shadowsocks代理,但是使用udp协议的DNS查询请求还是走的本地,而墙内对facebook,twitter,google这样的网站一般都进行了DNS污染,也就是解析他们的域名时会返回错误的IP地址。即使把DNS服务器设置成8.8.8.8或者OpenDNS也会因为其他服务器的DNS缓存而得到错误的IP地址,况且8.8.8.8等DNS服务器的流量早就已经被墙了,根本ping不通。

所以我们需要让DNS解析请求也经过SS代理服务器进行解析,但是redsocks不支持udp协议包的转发,而且有些SS代理服务器也不支持udp协议,所以此时我们就需要将udp协议包转换成tcp协议包,发送到SS代理服务器解析,然后再以tcp协议包发回,获得解析结果。这些步骤redsocks已经设计好了,只需要向上面贴的加上OUTPUT路由协议即可实现。

但是按上面的iptables配置添加了OUTPUT的路由协议,我Ubuntu本机应用的DNS解析都瘫痪了,但好在我可以让浏览器和其他服务直接挂Shadowsocks的客户端进行上网,也就是不走系统默认的DNS解析,而是让每个应用自主的使用代理解析DNS,于是也就忽略了这个缺陷。

下面贴一下DNS被污染后的解析结果:


可以看到IP被指向了非美国的IP,而curl这个IP是得不到任何相应的,下面贴一下经过redsocks udp转tcp协议后正确DNS解析的结果:

第四步:修改Ubuntu的DNS解析服务器

修改/etc/resolv.conf文件,如下将默认的127.0.0.1前面加上#,然后添加8.8.8.8做dns服务器

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)  

#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN  

#nameserver 127.0.0.1  

nameserver 8.8.8.8  

将DNS服务器改成8.8.8.8,以后的DNS请求就会转换成tcp协议通过SS代理服务器的转发到代理服务器当地的8.8.8.8解析后返回,防止DNS污染

保存以后一般立即生效,无需重新启动。

第五步:开启Ubuntu的Wifi热点功能

开启该项功能不麻烦,参考:http://www.linuxdiyf.com/linux/22118.html

好了,目前为止该做的都已经完成了,现在可以打开手机链接一下试试翻墙好使不好使,推荐首先测试国内网站,排除DNS污染的影响,比如百度搜索"ip"看看自己的ip是否已经变成了代理服务器的ip,然后再访问网站。

开发过程中遇到的一些坑:

首先就是Ubuntu分享出来的WIFI,除了小米手机意外的设备,比如电脑,iphone,Android手机连接都没有问题,但是小米手机一连接该WIfi我的笔记本无线网卡就会挂掉,Ubuntu提示“设备未就绪”,经过一番调试,发现这有可能和udp DNS转tcp有关,我当时为了减少WIFI信号上的冲突,将无线网卡的频率限制在了2.4G的波段4,于是小米手机链接后网卡挂是必现事件,后来将波段改成了自动之后,Ubuntu给我设置在了波段一,网卡挂掉的频率减少了很多,不是必现了。后来我又加上了WIFI密码,网卡几乎就不挂了(之前我都不设WIFI密码,任何设备都可以连接)。所以在这里推荐将波段设置为自动,并且设置连接密码来提高稳定性。


还有一个问题不得不说,redsocks和Shadowsocks-Qt5一样在Ubuntu上运行的稳定性很差,连接的人数一多,或者数据传输量比较大的时候会莫名其妙的挂掉,一般我都使用nslookup命令来查询DNS,如果能查寻到正确结果,说明redsocks和Shadowsocks都没问题,反之这两个服务至少挂掉了一个。

注:redsocks服务挂掉之后12345端口并不会关掉,使用netstat -ntl还是可以看到,但是如果shadowsocks服务挂了,那么1080端口就看不到了,通过netstat -ntl命令就可以查到是哪个服务挂了,如果是redsocks服务挂掉,可以使用

$ sudo service redsocks restart

来重启服务,一般重启后几十秒后就会恢复正常

为了提高redsocks的稳定性,我使用crontab每十分钟重启一次redsocks,但是发现崩溃更频繁了,因为有些时候redsocks restart命令本身就会让redsocks服务挂掉,反而降低了稳定性。直到现在我还是很苦恼。

应对高负载的多节点分流方案:

这么好的东西,只需连上一个WIFI就能实现全局翻墙,速度还比VPN快好多,当然会有很多人用,人数多了之后主要的瓶颈就在wifi信号和ss流量上,目前我使用的单个节点能平均能跑到10Mb/s,峰值能达到30Mb/s感觉还够用,但是如果以后人数更多,加上下载和看视频的流量,也许就捉襟见肘了。那么我们可以使用多个SS代理服务器进行分流,我打算这么做,1台延迟低的节点做DNS解析,主要是得益于redsocks的DNS和普通流量分离的做法,剩下几个节点做数据分流。分流方案我打算用ip地址进行分流,因为Ubuntu的无线网卡有DHCP功能,而且对连接设备的ip分配是随机的,于是可以根据设备的ip进行分段分流。

首先需要实现的是开启多个redsocks实例,监听不同的端口,这个比较容易实现,首先我们需要复制原来的配置文件并且进行修改,比如将原来的1080端口换成1081端口,然后再开启一个Shadowsocks客户端实例挂在另一个代理节点在127.0.0.1:1081接口,这个使用shadowsocks-Qt5很容易实现。我们把新的redsocks配置文件命名为 redsocks2

然后我们使用-c参数开启redsocks实例,监听两个不同的端口实现分流

$ sudo /usr/bin/redsocks -c /etc/redsocks

$ sudo /usr/bin/redsocks -c /etc/redsocks2

然后修改shadowsocks客户端,监听1080和1081两个端口分别使用不同的节点。


然后使用iptable路由协议根据ip地址进行分流

$ sudo iptables -t nat -I PREROUTING 5 -p tcp -m iprange --src-range 10.42.0.100-10.42.0.254 -j REDIRECT --to-ports 23456

$ sudo iptables -t nat -A PREROUTING -p tcp -s 10.42.0.0/16 -j REDIRECT --to-ports 12345

这样就将一半的流量分流至了另一个ss站点,该WIFI的带宽瞬间增长一倍。使用这种方案还能配置更多节点,让WIFI的瓶颈不再是带宽限制,最终实现全公司人翻墙工作。

 

另外有人会说这样使用iptables折腾是不是太麻烦了,如果有一个VPN帐号,Ubuntu原生在分享Wifi的时候就可以自动配置,根本不需要任何配置,用Windows使用VPN之后再加上WIFI共享精灵等软件共享出来的也是VPN翻墙后的,那我们为什么还非要搞的这么复杂呢?

Shadowsocks使用socks5协议,是一种将流量压缩并加密的优秀传输协议,相比起PPTP的VPN隧道具有几个明显的优势:

1、安全性好,数据传输经过了充分的加密,不容易被截获和拦截

2、稳定性好,L2TP掉线率很高,并且掉线以后往往缺乏自动重连的机制,但是Shadowsocks的客户端一般不会轻易掉线

3、服务器搭建成本低,不需要配置密钥,只需开启一个服务即可

4、速度快,Shadowsocks的速度在请求人数多的时候非常明显,并且可以配合final speed这样的软件进行加速,效果非常好

鉴于Shadowsocks的这些优点,现在已经很难买到PPTP协议的VPN了,即使买到,往往也很难连上。

---------------------

相关帖子:http://briteming.blogspot.com/2012/02/linux-redsockssocks5.html