之前一直使用 Caddy 作为Web服务器软件,但是自从升级Caddy2后配置大改,官方文档也不详细,就萌生了弃用Caddy的想法,刚好发现nginx1.15.2 版本新增了 $ssl_preread_protocol变量,通过该变量可以使用 stream反向代理时预先判断连接是否为SSL/TLS协议或者为非SSL/TLS协议,从而实现同一个端口来转发不同的业务,卧槽这不就是我想要的么,443端口复用啊。

使用 Docker 部署 Nginx

自己简单使用建议Docker Compose,省资源,迁移方便,只要整个目录打包迁移,然后docker-compose up -d一下就行。
这是我的 Docker Compose 配置文件

同时运行 Nginx 和 PHP 7.4,Nginx 依赖于 php 容器

  • services:
  • nginx:
  • image: nginx:latest
  • container_name: "nginx"
  • restart: always
  • environment:
  • - TZ=Asia/Shanghai
  • depends_on:
  • - "php"
  • ports:
  • - "80:80"
  • - "443:443"
  • volumes:
  • # 本地路径:Docker容器内路径
  • # 虚拟主机配置文件存放路径
  • - /data/web/webconf:/etc/nginx/conf.d:ro
  • # 映射整个 web 目录到 Docker 容器里
  • - /data/web:/data/web
  • # Nginx 核心配置文件
  • - /data/web/nginx-frontend.conf:/etc/nginx/nginx.conf:ro
  • networks:
  • - mynet
  • php:
  • image: php:7.4-fpm
  • container_name: "php"
  • restart: always
  • ports:
  • - "127.0.0.1:9000:9000"
  • environment:
  • - TZ=Asia/Shanghai
  • - LANG=zh_CN.UTF-8
  • volumes:
  • - /data/web:/data/web
  • networks:
  • - mynet
  • networks:
  • mynet:
复制

保存为 /data/docker-compose.yml

编写 Nginx 配置文件

别着急运行容器,没有/data/web/nginx-frontend.conf这个配置文件nginx容器运行不了的。

  • user nginx;
  • worker_processes 1;
  • error_log /var/log/nginx/error.log warn;
  • pid /var/run/nginx.pid;
  • events {
  • worker_connections 1024;
  • }
  • # 流量转发核心配置,主要增加这里,其他都是 Nginx 默认配置复制过来的
  • stream {
  • # 这里就是 SNI 识别,将域名映射成一个配置名,把xxx.com换成你的Trojan域名
  • map $ssl_preread_server_name $backend_name {
  • xxx.com trojan;
  • # 域名都不匹配情况下的默认值
  • default web;
  • }
  • # web,配置转发详情,转发到 444 端口,web 服务使用 444 端口接受 ssl 请求。
  • upstream web {
  • server 127.0.0.1:444;
  • }
  • # 匹配到 xxx.com 之后具体转发配置
  • upstream trojan {
  • # 注意修改 trojan:443
  • server trojan:443;
  • }
  • # 监听 443 并开启 ssl_preread
  • server {
  • listen 443 reuseport;
  • listen [::]:443 reuseport;
  • proxy_pass $backend_name;
  • ssl_preread on;
  • }
  • }
  • http {
  • include /etc/nginx/mime.types;
  • default_type application/octet-stream;
  • log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  • '$status $body_bytes_sent "$http_referer" '
  • '"$http_user_agent" "$http_x_forwarded_for"';
  • access_log /var/log/nginx/access.log main;
  • sendfile on;
  • #tcp_nopush on;
  • keepalive_timeout 65;
  • gzip on;
  • include /etc/nginx/conf.d/*.conf;
  • }
复制

额外说明

配置好后在/data目录里执行一下docker-compose up -d就会自动运行nginx 和 php,这里不列出 Trojan 的配置,你懂的,自行上网寻找。

之后新建 Nginx 虚拟主机配置请放在/data/web/webconf目录里,

复用端口后虚拟主机SSL监听端口变成了444,下面给出虚拟机配置文件的参考

  • server {
  • listen 80;
  • listen [::]:80;
  • server_name xxx;
  • #SSL Configuration
  • listen 444 ssl;
  • ssl_certificate /data/web/webcert/xxx.crt;
  • ssl_certificate_key /data/web/webcert/xxx.key;
  • ssl_session_timeout 5m;
  • ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  • ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  • ssl_prefer_server_ciphers on;
  • if ($scheme = http) {
  • return 301 https://$server_name$request_uri;
  • }
  • location / {
  • # 具体配置
  • }
  • }
复制

最后

这样配置好后你就可以畅快的在同一台VPS上使用Trojan和Web了,不过nginx不能自动获取SSL证书,建议使用acme.sh配合DNS验证来获取SSL证书,这里不说了,请查阅 https://acme.sh