利用 ss + redsocks + iptables 实现 ubuntu 翻墙

国内网络环境复杂,想要访问某些网站或服务,发现已经被墙。作为一个普通用户,我们可以有很多方式达到目的,客户端软件大多拥有界面,体验良好。那么对于运行在服务器上的程序想要访问被墙的服务,操作起来就不那么容易了。服务器没有界面也就没有那些操作简单的可视化客户端了,这时就想到了代理。我们需要一台运行在墙外的服务器,能正常访问被墙的服务,然后将被墙服务器的流量转发到墙外的服务器上去,解决方案就是 ss + redsocks + iptables。

ss

shadowsocks,基于 SOCKS5 协议的加密代理软件

安装

两台服务器都需要安装 ss

sudo apt-get update
sudo apt-get install python-pip
pip install shadowsocks

启动

墙外服务器后台启动 ss server

// $PORT: 设置 ss server 运行的端口号
// $PASSWORD: 设置 ss server 的密码
// -m aes-256-cfb: 加密方式
sudo ssserver -p $PORT -k $PASSWORD -m aes-256-cfb --user nobody -d start

被墙服务器后台启动 ss client

// $IP: ss server 的地址
// $PORT: ss server 的密码
// -b 127.0.0.1: 设置 ss client 运行的地址
// -l 1080: 设置 ss client 运行的端口
// -t 600: 设置连接 ss server 超时时间
sslocal -s $IP -p $PORT -b 127.0.0.1 -l 1080 -k $PASSWORD -t 600

redsocks

利用路由表将 TCP 连接转发到 SOCKS 或 HTTP 连接的工具

安装

被墙服务器安装

sudo apt-get update
sudo apt-get install redsocks

启动

被墙服务器后台启动
sudo service redsocks start

配置

一般使用默认配置文件 /etc/redsocks.conf 即可,如果 ss client 的启动参数不是默认的就需要自己设置

// /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 = 127.0.0.1;
        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;
        port = 1080;


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

        // login = "foobar";
        // password = "baz";
}

现在 ss 和 redsocks 都已经启动了,最后要利用 iptables 规划路由,将流量通过 redsocks 转发到 ss 上。

iptables

Linux 内核集成的 IP 信息包过滤系统

路由规划

// 新建路由转发表中的一个链 REDSOCKS
sudo iptables -t nat -N REDSOCKS
// 设置不需要代理转发的网段
// 目的为墙外代理服务器的数据包一定不能转发
sudo iptables -t nat -A REDSOCKS -d $SS_SERVER_IP -j RETURN
// 目的为局域网和本地回环地址的数据包不用转发
sudo iptables -t nat -A REDSOCKS -d 172.0.0.0/24 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
// 将数据包转发到 redsocks
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345
// 将 REDSOCKS 链的规则应用到经过 eth0 网卡的数据包
sudo iptables -t nat -A OUTPUT -p tcp -o eth0 -j REDSOCKS

以上的路由规则在服务器重启后就失效了,可以写到 shell 脚本中,开机后运行。

2015-11-20 13:481293