前段时间我基本没怎么用的裸奔 Shadowsocks 的端口被封掉了,在国内端口无法访问。我现在万分庆幸没把我 IP 给封掉,但是这个节点又不可缺少。虽然很奇怪,之前裸奔了那么久,也无事发生,这次只有几天就没了,腾讯云的问题吗?

这次于是试试加上 v2ray-plugin,混淆一下,看能够活多久。再次祈祷不要把我的域名墙了

主要用到的东西就是 shadowsocks-libevv2ray-plugin,以及 Nginx,当然还有 Docker 和 Docker-compose。主要思路就是 Nginx 转发到用了扩展的 Shadowsocks。

准备 Shadowsocks 镜像的相关文件

我想着最好大部分服务能够容器化,Shadowsocks-libev 不例外。官方提供的 shadowsocks-libev 似乎没有提供配置文件的环境变量,我也不知道配置文件能否覆盖原镜像里面 entrypoint.sh 的环境变量,于是我就打算在原镜像的基础上自定义一个镜像。
当然这是我的方法,不那么精明。

Dockerfile

自定义镜像当然就要编写 Dockerfile,我这里提供我自己编写的一个简单的版本。

FROM shadowsocks/shadowsocks-libev:latest
# 直接将shadowsocks组织提供的镜像作为基础
ENV SERVER_ADDR 0.0.0.0
ENV SERVER_PORT 8388
ENV PASSWORD=
ENV METHOD      aes-256-gcm
ENV TIMEOUT     300
ENV DNS_ADDRS    8.8.8.8,8.8.4.4
ENV TZ UTC
ENV ARGS=
# 没用到的环境变量
USER root
# 使用 root 用户

COPY ./v2ray-plugin_linux_amd64 /v2ray-plugin
COPY ./entrypoint.sh /entrypoint.sh
# 复制必须的文件

RUN chmod +x /v2ray-plugin
# 修改扩展的权限,让其可执行
COPY ./config.json /etc/shadowsocks-libev/
# 复制配置文件到默认目录
RUN chmod +x /entrypoint.sh
# 修改权限
CMD /entrypoint.sh
# 启动脚本

想到达的目的就是把扩展的可执行文件、配置以及修改后的 entrypoint.sh 放入镜像。

修改 entry-point.sh 和获得 v2ray-plugin

官方仓库的 entrypoint.sh 比较简单,生成密码,传入参数,这里稍微改一改就好了。

原文件

#!/bin/sh

if [[ -f "$PASSWORD_FILE" ]]; then
    PASSWORD=$(cat "$PASSWORD_FILE")
fi

if [[ -f "/var/run/secrets/$PASSWORD_SECRET" ]]; then
    PASSWORD=$(cat "/var/run/secrets/$PASSWORD_SECRET")
fi

exec ss-server \
      -s $SERVER_ADDR \
      -p $SERVER_PORT \
      -k ${PASSWORD:-$(hostname)} \
      -m $METHOD \
      -t $TIMEOUT \
      -d $DNS_ADDRS \
      -u \
      $ARGS

修改后

这里去掉了传入了部分环境变量,选择/etc/shadowsocks-libec/config.json作为配置文件,其它未作改动。

#!/bin/sh

if [[ -f "$PASSWORD_FILE" ]]; then
    PASSWORD=$(cat "$PASSWORD_FILE")
fi

if [[ -f "/var/run/secrets/$PASSWORD_SECRET" ]]; then
    PASSWORD=$(cat "/var/run/secrets/$PASSWORD_SECRET")
fi

exec ss-server \
      -c /etc/shadowsocks-libev/config.json \
      -u \
      $ARGS

下载 v2ray-plugin 二进制文件
前往 release 下载,这里选择最新的一个版本,架构选择 v2ray-plugin-linux-amd64,根据你自己的机器选择就好,我的是 x86 Debian,所以选择这个,下载好解压即可。

编写配置

新建一个 config.json,填入以下内容:

{
    "server":"0.0.0.0",
    "mode":"tcp_only",
    "server_port":8388,
    "local_port":1080,
    "password":"replace_with_your_password", # 填入你的密码
    "timeout":5,
    "method":"chacha20-ietf-poly1305", 
    "plugin":"v2ray-plugin", 
    "plugin_opts":"server;host=0.0.0.0;path=/ss" 
}

上述配置中:

  • plugin 后是是扩展二进制可执行文件的位置,上述 Dockerfile 我把可执行文件放在了根目录,并重命名了为 v2ray-plugin,这里这么填就可以了。
  • plugin_opts 是扩展的选项,在这个环境下,需要注意的是 path 后的目录,也就是你 Nginx 反代和最终代理客户端配置的目录,这里填入 /ss。具体可以参考Use v2ray-plugin after Nginx · Issue #48 · shadowsocks/v2ray-plugin。由于是在 Nginx 的后端,Nginx 负责了 TLS,这里禁用了 TLS,默认开启了 MUX,这在后面的 clash 的配置会用到。
  • 加密方式 chacha20-ietf-poly1305 推荐使用。

Docker 相关

这里图方便,就用 Docker-compose 部署了。
这里会用到两个容器,一个自然是上述 Dockerfile,另一个是 Nginx。Docker-compose 可以在部署是自动编译是构建镜像,于是这里就不再手动构建了,
Docker-compose.yml

version: "3"
services:
  shadowsocks:
    build: ./
    container_name: shadowsocks
    volumes:
      - ./config.json:/etc/shadowsocks-libev/config.json:ro
    restart: unless-stopped

  web:
    image: nginx:mainline-alpine
    container_name: nginx
    volumes:
      - "./nginx_sites_conf:/etc/nginx/conf.d/"
      - "./ssl:/etc/ssl"
      # - ./nginx:/snippets
    ports:
      - "80:80"
      - "443:443"
    restart: unless-stopped

关于 Nginx 镜像更详细的使用方法请参考文档写在一起就略显没有重点了

新建一个 shadowsocks.conf,即 Nginx 的配置文件,名字随意的,内容如下:

server {
        listen 443 ssl;
        server_name example.com; # 你的域名

        access_log    off; # 关闭日志输出

        ssl_certificate /etc/ssl/fullchain.pem;
        ssl_certificate_key     /etc/ssl/privkey.pem;

        location /ss {
        proxy_redirect off;
        proxy_pass http://shadowsocks:8388; 
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

        location / {
                return 404;
        }

}

需要注意的是:

  • 请自己准备 Nginx 需要的证书,例如privkey.pem fullchain.pem,并放在 ./ssl 下,并更改相关文件名称。可以使用 swag 镜像自动获得来自 letsencypt 的证书。
  • proxy_pass 后面填写的 shadowsocks 是 docker 根据 container_name 自动给容器赋予的域名,如果两个容器在同一个网络,可以使用此域名链接。上述在同一个 docker-compose.yml 内的容器默认在同一个网络。
  • 第二个 location 是给 server 一个默认的响应。

目录结构和启动容器

将上述文件放在一个目录里,有如下目录树:

➜  shadowsocks-libev tree ./
./
|-- Dockerfile
|-- config.json
|-- docker-compose.yml
|-- entrypoint.sh
|-- nginx_sites_conf
|   `-- shadowsocks.conf
|-- ssl
|  |-- privkey.pem
|  `-- fullchain.pem
`-- v2ray-plugin_linux_amd64

在这里算准备完成了,执行:docker-compose up -d 即可构建镜像并部署服务。docker logs -f shadowsocks 可以查看容器的日志,shadowsocks 是容器名称,例如 docker logs -f nginx
也可以 docker-compose up,容器会在前台运行,输出相关日志,方便调试。

Clash 相关

在你的 proxies: 内填入以下内容:

- {name: proxy_name, server: server_ip, port: 443, type: ss, plugin: v2ray-plugin, plugin-opts: {mode: websocket, host: example.com, path: /ss, tls: true, mux: true}, cipher: chacha20-ietf-poly1305, password: replace_with_your_password}
  • 更改 name,填入服务器 IP、密码和域名。
  • 注意 mux 是默认开启的,客户端这里也需要启用。
  • 更详细的请参考其他文章,我是 Subconverter 在负责生成订阅。

image.png

Last modification:November 12th, 2021 at 12:45 pm