From 11b9017a077e4c2e5d6ba05f45616b0aa33c8d2e Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Thu, 6 Oct 2022 18:02:31 +0800 Subject: [PATCH] =?UTF-8?q?blog:=20=E5=88=A9=E7=94=A8=20SNI=20=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=20TLS=20=E8=BF=9E=E6=8E=A5=E5=AE=9E=E7=8E=B0=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=E5=A4=8D=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 1 + components/Footer.js | 2 +- data/blog/network-freedom-with-vps.md | 240 ++++++++++++++++++++++++++ data/blog/sni-reverse-proxy.md | 4 +- 4 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 data/blog/network-freedom-with-vps.md diff --git a/.vscode/settings.json b/.vscode/settings.json index b6cf8e3..662a3ed 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "outbounds", "rprx", "VLESS", + "vmess", "xtls" ] } diff --git a/components/Footer.js b/components/Footer.js index 4a15d39..d4e2121 100644 --- a/components/Footer.js +++ b/components/Footer.js @@ -22,7 +22,7 @@ export default function Footer() { {siteMetadata.title}
- + Tailwind Nextjs Theme
diff --git a/data/blog/network-freedom-with-vps.md b/data/blog/network-freedom-with-vps.md new file mode 100644 index 0000000..0ea0e5b --- /dev/null +++ b/data/blog/network-freedom-with-vps.md @@ -0,0 +1,240 @@ +--- +title: 利用一台小鸡实现网络自由 +date: '2022-10-06' +tags: ['SNI', 'TLS', 'Reverse Proxy', '反向代理', '正向代理', ‘内网穿透', 'Caddy', 'Xray', 'Vless'] +draft: false +summary: SNI Proxy 进行 TLS 分流;Caddy 对网站和 Xray 进行反向代理;Xray 实现正向、反向代理(内网穿透)。 +--- + +## 前言 + +由于条件所限,我在住所使用了一台 AMD 小主机运行了 PVE,上面跑了许多服务,他们有一个共同点——具有 Web UI。另一方面,我的宽带使用共享公网 IP,使用 Full Cone NAT,这就导致我在外难以方便地访问内网服务。为了解决这个令人不爽的问题,我准备使用 VPS 主机作为中间人,用于反射相关流量。 + +比较悲剧的是,在撰写本文时,VPS 的 443 端口被干掉……不过还好,VPS 即将到期,如果不能恢复,就换别的了。 + +## 网络拓扑图 + +简单画一下,大概网络拓扑长下面这样: + +```mermaid +graph TB; +subgraph CLIENT +BROWSER(Browser) +XRAY-C(Xray) +GIT-C(Git) +end + +subgraph VPS +SNI-PROXY(SNI Proxy) +CADDY-S(Caddy) +XRAY-S(Xray) +end + +subgraph HOME +CADDY-H(Caddy) +XRAY-H(Xray) +GIT-S(Git) +end + +BROWSER--https://www.example.com:443-->SNI-PROXY--https://www.example.com:443-->CADDY-S +BROWSER--https://home.example.com:443-->SNI-PROXY--https://home.example.com:443-->XRAY-H--https://home.example.com:443-->CADDY-H +XRAY-C--vless://vless.example.com:443-->SNI-PROXY--vless://vless.example.com:443-->XRAY-S +XRAY-C--vmess://vmess.example.com:443-->SNI-PROXY--vmess://vmess.example.com:443-->CADDY-S--vmess://vmess.example.com WITHOUT LTS-->XRAY-S +BROWSER--http://www.example.com:80-->CADDY-S +GIT-C--git://git.example.com:2222-->XRAY-S--git://git.example.com:2222-->XRAY-H--git://git.example.com:2222-->GIT-S +``` + +从上图中可以看到,VPS 公网 443 端口由 SNI Proxy 监听,80 端口由 Caddy 监听,2222 端口作为 家庭 Git 服务器的透传端口,由 Xray 直接监听并反射(relay)给家庭 Git 服务。 + +SNI Proxy 通过对 TLS 的 SNI 对流量进行区分,将访问部署在家庭中的网站的流量直接转发给 Xray,再由 Xray 根据规则转发给家庭中的 Caddy 服务,最后由家庭中的 Caddy 服务将 HTTPS 流量转为 HTTP 流量,并转发给目标服务。对于 VLESS 流量,将转发给 Xray 对应端口处理;对于 vmess 和其他网站流量,转发给 Caddy 的 443 端口处理。 + +Caddy 接收到 443 端口的流量,将根据域名等规则处理并转发给对应服务,如果是 vmess 流量,将扒掉 TLS 层并交由 Xray 处理。Caddy 还接收 80 端口的流量,这部分流量基本上都转发给对应 HTTP 服务进行处理。 + +## 部署 + +### Docker Compose + +```yml +version: '3.9' + +networks: + caddy: + xray: + +volumes: + caddy-data: + caddy-config: + acme-sh-data: + +services: + xray: + image: teddysun/xray + container_name: xray + restart: always + ports: + - '2222:2222' + networks: + - xray + volumes: + - ./xray/config.yml:/etc/xray/config.yml + - acme-sh-data:/certs + command: 'xray -c=/etc/xray/config.yml' + + caddy: + image: caddy:2 + container_name: caddy + restart: always + ports: + - '80:80' + networks: + - caddy + - xray + volumes: + - $PWD/caddy/Caddyfile:/etc/caddy/Caddyfile + - $PWD/site:/srv + - caddy-data:/data + - caddy-config:/config + - acme-sh-data:/certs + + sniproxy: + image: tommylau/sniproxy + container_name: sniproxy + restart: always + networks: + - caddy + - xray + ports: + - '443:443' + volumes: + - $PWD/sniproxy:/etc/sniproxy + - /var/log/sniproxy:/var/log/sniproxy + acme.sh: + image: neilpang/acme.sh:dev + container_name: acme.sh + restart: always + volumes: + - acme-sh-data:/acme.sh + env_file: acme.env + command: 'daemon' +``` + +### SNI Proxy 配置 + +文件位于 `sniproxy/sniproxy.conf + +```conf +user nobody +group nogroup + +# PID file +pidfile /var/run/sniproxy.pid + +error_log { + # Log to the daemon syslog facility + # syslog deamon + + # Alternatively we could log to file + filename /var/log/sniproxy/sniproxy.log + + # Control the verbosity of the log + priority notice +} + +listen 443 { + proto tls + table https_hosts + + access_log { + filename /var/log/sniproxy/https_access.log + priority notice + } +} + +table https_hosts { + vmess.example.com caddy:443 # vmess + vless.example.com xray:443 # VLESS + .*\.example\.com xray:8443 # HTTPS tunnel + www.example.com caddy:443 # VPS vhost +} +``` + +### Caddy 配置 + +文件位于 `caddy/Caddyfile`。 + +```caddyfile +www.example.com { + encode zstd gzip + reverse_proxy some-host:80 +} + +vmess.example.com { + reverse_proxy h2c://xray:80 // vmess +} +``` + +### Xray 配置 + +文件位于 `xray/config.yml` + +```yml +--- +inbounds: + - tag: vless-xtls.in + listen: 0.0.0.0 + port: 443 + protocol: vless + settings: + clients: + - id: + flow: xtls-rprx-direct + decryption: none + streamSettings: + network: tcp + security: xtls + xtlsSettings: + serverName: vless.example.com + alpn: + - h2 + - http/1.1 + certificates: + - certificateFile: /certs/*.example.com/fullchain.cer + keyFile: /certs/*.example.com/*.example.com.key + falklbacks: + - name: 'vmess.ivanli.cc' + dist: 80 + xver: 1 + - dest: 'caddy:80' + xver: 1 + - listen: 0.0.0.0 + port: 80 + protocol: vmess + settings: + clients: + - id: + decryption: none + streamSettings: + network: h2 + security: none + httpSettings: + path: / + host: + - vmess.example.com + # ... 其他配置 ... +``` + +关于反向代理及泛域名证书相关配置,参考[使用 Xray、acme.sh、Docker Compose 搭建内网穿透服务](https://ivanli.cc/blog/build-an-frp-using-xray-acme.sh-docker-compose)。 + +### 启动服务 + +启动服务前,确保你的配置都完成了。之后在 `docker-compose.yml` 同级目录下执行下面的命令: + +```bash +docker compose up -d +``` + +如果有防火墙,注意放行端口。 + +## 方案浅析 + +上述方案主要解决了一个问题,443 端口的复用。使得所有**“HTTPS 流量”**都流向 443 端口,显得非常治愈。因为使用了境外服务器,为了避免被误杀,实现了站点伪装,这样在一定程度上避免被主动探测发现问题。可是在撰写本文前,翻车了,原因可能是客户端指纹特征导致的。因为除了穿透服务的客户端是完全可控的,能通过配置[开启 uTLS 来规避](https://t.ivanli.cc/UFImlX),但是在网关上的 Clash 客户端却没提供相关配置选项。大意了。 diff --git a/data/blog/sni-reverse-proxy.md b/data/blog/sni-reverse-proxy.md index ddc3435..f66b1ca 100644 --- a/data/blog/sni-reverse-proxy.md +++ b/data/blog/sni-reverse-proxy.md @@ -51,9 +51,11 @@ VLESS 是一种安全高效的数据传输协议,其支持的 xTLS 协议非 使用 Docker Compose 部署。 -部署步骤以后和其他内容一起,整理成一套方案后再一起分享,这里就先略过,以下是用到的容器: +以下是用到的容器: - [caddy - Official Image | Docker Hub](https://registry.hub.docker.com/_/caddy) - [tommylau/sniproxy - Docker Image | Docker Hub](https://registry.hub.docker.com/r/tommylau/sniproxy) - [neilpang/acme.sh - Docker Image | Docker Hub](https://registry.hub.docker.com/r/neilpang/acme.sh) - [gists/xray - Docker Image | Docker Hub](https://registry.hub.docker.com/r/gists/xray) + +部署方式:[利用一台小鸡实现网络自由](./network-freedom-with-vps)