故事是这样的,原导师离职,所以更换了导师,加入了一个搞分布式文件系统的课题组。暂时给的课题是先学习 ceph 和 ipfs,并把环境搭建起来分析源码。导师留下了几台电脑没人用,所有就拿过来重整了一下。

本学期校园网打击个人 WiFi 的行为可谓到了极端的地步,根据脚本日志显示,路由器通过 drcom.py 连接的方式平均每天要掉 8 次以上,而且还会每隔十几分钟就中断连接数十秒,真是非常难受了。于是暂时的解决方案是这样的:

20181130202365.png

上网账号只有一个,只能一台设备登录,让路由器作为登录终端的方式已经逐渐不好用了,这里让实验室的主机登录,寝室的路由器只作为发射 WiFi 之用,无线设备通过 WiFi 连接到校园网,然后通过全局的 shadowsocks 代理到实验室主机,从而实现到外网的连接。基于这个思路,记录一个 Linux 上通过代理连接外网的方案。


数据传递的过程

两台主机分别取名叫 Client 和 SS。其中 SS 是登录了上网账号的主机;Client 是希望被代理的主机。

  1. 首先 Client 将所有 http/https 的数据包转到 socks 协议转发到本机 shadowsocks-local 监听的端口处;
  2. shadowsocks-local 再将接收到的数据转发给 SS 上的 shadowsocks-server 监听的端口;
  3. shadowsocks-server 代理 Client 的数据转发给目的服务器。

http/https 转发到 shadowsocks-local 的配置

Linux:privoxy

  • 如果系统是 Linux,则可以使用 privoxy 实现 http/https 到 socks 的转发。在 CentOS 中,privoxy 在 epel 软件仓库中,可以通过 yum 直接安装 epel,之后更新包列表,再安装 privoxy 即可:
$ yum install epel-release
$ yum makecache
$ yum install privoxy
  • 修改配置文件配置 privoxy,添加如下代码,第一行说明 privoxy 监听本机的 8118 端口,第二行是转发到本机的 1080 端口:
$ vim /etc/privoxy/config
listen-address 0.0.0.0:8118
forward-socks5t / 127.0.0.1:1080 .
  • 修改完毕后启动 privoxy 服务:
$ systemctl enable privoxy
$ systemctl restart privoxy
  • 配置 profile 将本机的所有 http/https 转发到 8118 端口,可以修改本用户的环境变量 ~/.bashrc 或 ~/.bash_profile 或者全局环境变量 /etc/profile,添加如下环境变量:
$ vim /etc/profile
export http_proxy=http://127.0.0.1:8118
export https_proxy=http://127.0.0.1:8118
$ source /etc/profile

完成以上步骤后即完成了 http/https 转发到 shadowsocks-local 的配置

ssh 的转发配置
上面的配置只能转发 http/https 请求,但是 ssh 并不会被转发,例如 git 只能使用 http 不能使用 ssh 很难受,所以再加个 ssh 的转发。修改 ~/.ssh/config,没有则创建,添加如下代码:

$ vim ~/.ssh/config
proxyCommand connect -S 127.0.0.1:1080 %h %p

其中在 CentOS 中 connect 需要下载编译,如下:

$ yum install hg
hg clone https://bitbucket.org/gotoh/connect
cd connect
make        # 如果没有安装 gcc 则 yum install gcc 安装之
mv connect /usr/local/bin/connect

以上设置直接将 ssh 的包转发给 shadowsocks-local。

Windows:proxifier
如果系统是 Windows,则可以使用 proxifier 实现全局的转发。


shadowsocks-local 转发到 shadowsocks-server 的配置

  • 安装 pip 并在 pip 中安装 shadowsocks:
yum install python2-pip
pip install shadowsocks
  • 添加配置文件如下:
$ vim /etc/shadowsocks.json
{
    "server":"xx.xx.xx.xx",       运行 shadowsocks-server 的主机 IP 地址
    "server_port":xxx,            运行 shadowsocks-server 的主机监听的端口
    "local_address":"127.0.0.1",
    "local_port":1080,            本地 shadowsocks-local 监听的端口
    "password":"xxxx",            shadowsocks-server 上设置的口令
    "timeout":300,
    "method":"aes-256-cfb",
    "fast_open":false,
    "workers":1
}
  • 启动 shadowsocks-local 服务
$ nohup sslocal -c /etc/shadowsocks.json 2>&1 /dev/null &

也可以将 sslocal 注册为 systemd 的服务,添加如下代码:

$ vim /etc/systemd/system/shadowsocks-local.service
[Unit]
Description=Shadowsocks Local
After=network.target
[Service]
User=nobody
Group=nobody
ExecStart=/usr/bin/sslocal -c /etc/shadowsocks.json
Restart=on-abort
[Install]
WantedBy=multi-user.target

再通过 systemctl 启动:

$ systemctl enable shadowsocks-local
$ systemctl start shadowsocks-local

shadowsocks-server 上的配置

在能够连接外网的主机上,配置 shadowsocks-server 服务,这里仍然采用 pip 提供的 shadowsocks。

  • Linux 上的配置,添加配置文件如下:
$ vim /etc/shadowsocks.json
{
    "server":"0.0.0.0",
    "server_port":xxx,                shadowsocks-server 监听的端口
    "local_address":"127.0.0.1",
    "local_port":12450,               shadowsocks-server 对外转发请求时的端口,随便填
    "password":"xxxx",                shadowsocks-server 接受 local 连接的口令
    "timeout":300,
    "method":"aes-256-cfb",
    "fast_open":false,
    "workers":1
}
  • 启动 shadowsocks-server 服务
$ nohup ssserver -c /etc/shadowsocks.json 2>&1 /dev/null &

也可以将 ssserver 注册为 systemd 的服务,添加如下代码:

$ vim /etc/systemd/system/shadowsocks-server.service
[Unit]
Description=Shadowsocks Server
After=network.target
[Service]
User=nobody
Group=nobody
ExecStart=/usr/bin/ssserver -c /etc/shadowsocks.json
Restart=on-abort
[Install]
WantedBy=multi-user.target

再通过 systemctl 启动:

$ systemctl enable shadowsocks-server
$ systemctl start shadowsocks-server
  • Windows 上的配置
    同上配置好 shadowsocks.json 文件后,这里采用的批处理脚本启动。新建一个 ssserver.cmd,输入:
ssserver.exe -c shadowsocks.json

之后双击启动。


总结

整体组织如下图,有几个比较重要的端口设置。

20181130202365.jpg

  1. 首先 ssserver 监听一个端口,将所有发到该端口的数据包进行解包并进行转发;因此 sslocal 就必须要设置正确的服务器 IP 和 端口以及连接的口令。
  2. sslocal 监听本机 127.0.0.1 的某一个端口,将所有转发到该端口的数据包进行加密并发到 ssserver 上;因此 privoxy 和 connect 以及 proxifier 都必须要设置正确的 sslocal 端口,使得能够成功的将数据包转发给 sslocal。
  3. proxifier 可以设置直接将所有 IP 数据包转发给 sslocal,而 privoxy 需要在环境变量中设定代理;connect 也需要在 ssh 的配置文件中指定代理。

(完)