Palemoons' Archive
Palemoons' Archive

原生nginx反代服务配置

此次彻底抛弃面板
发布于 202676|遵循CC BY-NC-SA 4.0许可

过去我的服务通过frp + nginx-proxy-manager的方案实现公网访问。但是面板形式的npm经常会遇到一些细枝末节的地方遇上小bug,不影响正常运行但总觉得有些膈应。另外任何暴露在公网上的面板都会有被爆破的风险。于是趁着时间充足,我打算退回最原始的nginx反代方案,手工配置conf文件并注册证书。

我的内网穿透方案总体没变,还是保持了如下结构:

  • 阿里云跳板机:

    • frps:开内网穿透服务

    • nginx:负责反代

    • acme.sh:注册并续签证书

  • 内网服务器:

    • frpc:与跳板机建立连接

    • 各种内网服务

完成部署后,访问链路仍然不变:

用户 => 二级域名 => Nginx反代 => 本地映射端口 => frp => 内网服务

阿里云配置

阿里云控制面板需要配置三处地方。首先需要将域名指向云服务器IP,其次设置防火墙打开对应的监听端口,最后申请一个 accessKey 用于泛域名证书申请。

其中,在控制台中至少设置下面两个域名解析:

text
1@ A VPS_IP 2* A VPS_IP

同时,accessKey面板处申请一个新的accessKey,申请后妥善保存:

bash
1Ali_Key="AccessKeyId" 2Ali_Secret="AccessKeySecret"

FRP配置

我们没有特殊需求,因此frps只需要做最简单的配置:

toml
1bindPort = 1234 2auth.token = "auth_token"

使用systemd创建守护进程,frps.service配置如下:

ini
1# /etc/systemd/system/frps.service 2[Unit] 3Description = frp server 4After = network.target syslog.target 5Wants = network.target 6 7[Service] 8Type = simple 9ExecStart = /home/palemoons/frps/frps -c /home/palemoons/frps/frps.toml 10 11[Install] 12WantedBy = multi-user.target

frpc照旧配置:

toml
1serverAddr = "example.com" 2serverPort = 1234 3auth.token = "auth_token" 4 5[[proxies]] 6name = "proxy_name" 7type = "tcp" 8localPort = 443 9localIP = "127.0.0.1" 10remotePort = 4000

unraid没有默认的守护进程,打包成一个docker容器又有点小题大做,因此我现在使用的是nohup挂在后台运行:

bash
1cp /boot/config/frpc/frpc /usr/local/bin/frpc 2chmod +x /usr/local/bin/frpc 3 4/usr/local/bin/frpc -c /boot/config/frpc/frpc_ssh.toml > /var/log/frpc_ssh.log 2>&1 & 5/usr/local/bin/frpc -c /boot/config/frpc/frpc_app.toml > /var/log/frpc_app.log 2>&1 &

证书申请

使用 acme.sh 作为 ACME 客户端,通过阿里云 DNS API 完成 DNS-01 验证。由于默认的 ZeroSSL 方案在续期的时候会遇上网络问题,因此需要手动设置申请 Let’s Encrypt 泛域名证书。证书覆盖根域名 example.com 和所有二级域名 *.example.com,无需为每个反向代理服务单独申请证书。

如果跳板机还没有 acme.sh,需要先安装:

bash
1curl https://get.acme.sh | sh 2source ~/.bashrc

设置阿里云 accessKey:

bash
1export Ali_Key="AccessKeyId" 2export Ali_Secret="AccessKeySecret"

申请根证书:

bash
1acme.sh --set-default-ca --server letsencrypt 2acme.sh --issue --server letsencrypt --dns dns_ali \ 3 -d example.com \ 4 -d '*.example.com' \ 5 --keylength ec-256

安装证书:

bash
1acme.sh --install-cert -d example.com --ecc \ 2 --key-file /etc/nginx/ssl/example.com/key.pem \ 3 --fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \ 4 --reloadcmd "sudo nginx -t && sudo systemctl reload nginx"

后续各站点配置统一引用该目录下的证书文件:

nginx
1ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; 2ssl_certificate_key /etc/nginx/ssl/example.com/key.pem;

NGINX配置

nginx在这里用于处理各种域名请求,接着将请求转发到对应端口上。我们需要用到的配置目录结构如下:

text
1/etc/nginx/ 2 nginx.conf 3 snippets/ 4 proxy-common.conf 5 sites-available/ 6 default 7 example.com.conf 8 sub1.example.com.conf 9 sub2.example.com.conf 10 sub3.example.com.conf 11 ... 12 sites-enabled/ 13 default => /etc/nginx/sites-available/default 14 example.com.conf => /etc/nginx/sites-available/example.com.conf 15 ... 16 ssl/ 17 example.com.conf/ 18 fullchain.pem 19 key.pem

下面简单说明一下各文件的配置内容。

nginx.conf

主配置文件,负责定义全局运行参数,不直接配置具体网站或反代服务,只负责加载其他配置。

nginx
1user www-data; 2worker_processes auto; 3pid /run/nginx.pid; 4 5events { 6 worker_connections 1024; 7} 8 9http { 10 include /etc/nginx/mime.types; 11 default_type application/octet-stream; 12 13 sendfile on; 14 tcp_nopush on; 15 tcp_nodelay on; 16 17 keepalive_timeout 65; 18 types_hash_max_size 2048; 19 20 server_tokens off; 21 22 access_log /var/log/nginx/access.log; 23 error_log /var/log/nginx/error.log; 24 25 gzip on; 26 gzip_disable "msie6"; 27 28 map $http_upgrade $connection_upgrade { 29 default upgrade; 30 '' close; 31 } 32 33 include /etc/nginx/sites-enabled/*; 34}

具体各二级域名如何配置我们放在/etc/nginx/sites-enabled/*中。

snippets

放置一些通用的配置片段,这里我们只设置了一个proxy-common.conf,设置好反向代理的通用片段:

nginx
1proxy_http_version 1.1; 2 3proxy_set_header Host $host; 4proxy_set_header X-Real-IP $remote_addr; 5proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 6proxy_set_header X-Forwarded-Proto $scheme; 7proxy_set_header X-Forwarded-Host $host; 8 9proxy_set_header Upgrade $http_upgrade; 10proxy_set_header Connection "upgrade"; 11 12proxy_buffering off; 13proxy_request_buffering off; 14 15client_max_body_size 1024m; 16proxy_read_timeout 3600s; 17proxy_send_timeout 3600s;

sites-available

存放所有可用的站点配置文件,但如果不链接至sites-enabled处,则不生效。

text
1sites-available/ 2 default 3 example.com.conf 4 sub1.example.com.conf 5 sub2.example.com.conf 6 sub3.example.com.conf 7 ...

其中default是兜底的回退配置,example.conf是根域名主页配置,剩余的为其他子域名配置。

default

目标是将其他未设置的域名或uri访问重定向至根目录,同时禁用 http 访问。

nginx
1server { 2 listen 80 default_server; 3 listen [::]:80 default_server; 4 5 server_name _; 6 7 return 301 https://c/; 8} 9 10server { 11 listen 443 ssl default_server; 12 listen [::]:443 ssl default_server; 13 http2 on; 14 15 server_name _; 16 17 ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; 18 ssl_certificate_key /etc/nginx/ssl/example.com/key.pem; 19 20 return 301 https://example.com/; 21}

example.com.conf

用于配置根域名网页配置,响应文件为/var/www/example.com/index.html

nginx
1server { 2 listen 80; 3 listen [::]:80; 4 5 server_name example.com www.example.com; 6 7 return 301 https://example.com/; 8} 9 10server { 11 listen 443 ssl; 12 listen [::]:443 ssl; 13 http2 on; 14 15 server_name www.example.com; 16 17 ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; 18 ssl_certificate_key /etc/nginx/ssl/example.com/key.pem; 19 20 return 301 https://example.com/; 21} 22 23server { 24 listen 443 ssl; 25 listen [::]:443 ssl; 26 http2 on; 27 28 server_name example.com; 29 30 ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; 31 ssl_certificate_key /etc/nginx/ssl/example.com/key.pem; 32 33 root /var/www/example.com; 34 index index.html; 35 36 location = / { 37 try_files /index.html =404; 38 } 39 40 location / { 41 return 301 https://example.com/; 42 } 43}

sub.example.com.conf

配置各二级域名,首先禁用 http 访问,然后将对该域名的访问转发至真正监听的端口上。

nginx
1server { 2 listen 80; 3 server_name sub.example.com; 4 return 301 https://$host$request_uri; 5} 6 7server { 8 listen 443 ssl; 9 http2 on; 10 server_name sub.example.com; 11 12 ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem; 13 ssl_certificate_key /etc/nginx/ssl/example.com/key.pem; 14 15 location / { 16 proxy_pass http://127.0.0.1:1234; 17 include /etc/nginx/snippets/proxy-common.conf; 18 } 19}

sites-enabled

存放实际生效的站点配置,通过刚刚说的软链接引用sites-available文件,例如:

bash
1ln -s /etc/nginx/sites-available/sub1.example.com.conf /etc/nginx/sites-enabled/

若要停用某站点,移除该文件夹中的软链即可。

Comments