avatar


一种基于nginx的反向代理策略

DNS

通过域名服务商,配置一个记录类型为"A"的解析,记录值为服务器的公网IP。

DNS的配置

nginx

Windows

然后在服务器上启动nginx。

提前启动nginx的原因,是为下一步的证书申请做准备。
启动nginx后,我们在浏览器输入域名,理论上应该能看到如下的网页。

nginx

如果看不到,除了DNS的配置、nginx的配置外,其他可能的原因有:

  • 云服务商的网络策略
    通过云服务商的管理页面调整
  • 虚拟机的防火墙策略

Ubuntu

通过apt安装并启动nginx:

1
2
3
4
5
sudo apt update
sudo apt install nginx -y

sudo systemctl start nginx
sudo systemctl enable nginx

启动nginx后,在浏览器输入域名,理论上应该能看到nginx的默认欢迎页。

如果看不到,除了DNS的配置、nginx的配置外,其他可能的原因有:

  • 云服务商的网络策略
    通过云服务商的管理页面调整

  • 虚拟机的防火墙策略(ufw)

    1
    2
    sudo ufw allow 80
    sudo ufw allow 443

证书

证书申请

Windows

通过win-acme申请证书。
官网:https://www.win-acme.com
双击wacs.exe即可运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
A simple Windows ACMEv2 client (WACS)
Software version 2.2.2.1449 (release, trimmed, standalone, 64-bit)
Connecting to https://acme-v02.api.letsencrypt.org/...
Connection OK!
Scheduled task looks healthy
Please report issues at https://github.com/win-acme/win-acme

N: Create certificate (default settings)
M: Create certificate (full options)
R: Run renewals (0 currently due)
A: Manage renewals (1 total)
O: More options...
Q: Quit

Please choose from the menu: m
  • 选择m,完全自行设定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Running in mode: Interactive, Advanced
Source plugin IIS not available: No supported version of IIS detected.

Please specify how the list of domain names that will be included in the
certificate should be determined. If you choose for one of the "all bindings"
options, the list will automatically be updated for future renewals to
reflect the bindings at that time.

1: Read bindings from IIS
2: Manual input
3: CSR created by another program
C: Abort

How shall we determine the domain(s) to include in the certificate?: 2
  • 选择2,手工输入。
1
2
3
4
Description:        A host name to get a certificate for. This may be a
comma-separated list.

Host: 【域名】
  • 输入域名
1
2
3
Source generated using plugin Manual: 【域名】

Friendly name '[Manual] 【域名】'. <Enter> to accept or type desired name: <Enter>
  • 确认域名,如果无误,直接回车即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
By default your source identifiers are covered by a single certificate. But
if you want to avoid the 100 domain limit, want to prevent information
disclosure via the SAN list, and/or reduce the operational impact of a single
validation failure, you may choose to convert one source into multiple
certificates, using different strategies.

1: Separate certificate for each domain (e.g. *.example.com)
2: Separate certificate for each host (e.g. sub.example.com)
3: Separate certificate for each IIS site
4: Single certificate
C: Abort

Would you like to split this source into multiple certificates?: 4
  • 选择申请的证书的类型,这里选择4即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
The ACME server will need to verify that you are the owner of the domain
names that you are requesting the certificate for. This happens both during
initial setup *and* for every future renewal. There are two main methods of
doing so: answering specific http requests (http-01) or create specific dns
records (dns-01). For wildcard identifiers the latter is the only option.
Various additional plugins are available from
https://github.com/win-acme/win-acme/.

1: [http] Save verification files on (network) path
2: [http] Serve verification files from memory
3: [http] Upload verification files via FTP(S)
4: [http] Upload verification files via SSH-FTP
5: [http] Upload verification files via WebDav
6: [dns] Create verification records manually (auto-renew not possible)
7: [dns] Create verification records with acme-dns (https://github.com/joohoi/acme-dns)
8: [dns] Create verification records with your own script
9: [tls-alpn] Answer TLS verification request from win-acme
C: Abort

How would you like prove ownership for the domain(s)?: 1
  • 选择1,通过本地文件的方式验证。
1
2
3
4
Description:        Root path of the site that will serve the HTTP validation
requests.

Path: C:\APP\nginx-1.22.1\html
  • 输入本地文件的根目录
    这也是为什么要提前启动nginx的原因。如果nginx没有启动成功,win-acme的验证会失败。
1
2
3
4
5
Description:        Copy default web.config to the .well-known directory.
Default: False
Argument: False (press <Enter> to use this)

Copy default web.config before validation? (y/n*) - no
  • 在验证之前,不保存默认的配置。
1
2
3
4
5
6
7
8
9
10
After ownership of the domain(s) has been proven, we will create a
Certificate Signing Request (CSR) to obtain the actual certificate. The CSR
determines properties of the certificate like which (type of) key to use. If
you are not sure what to pick here, RSA is the safe default.

1: Elliptic Curve key
2: RSA key
C: Abort

What kind of private key should be used for the certificate?: 1
  • 私钥类型,选择第一种。
1
2
3
4
5
6
7
8
9
10
11
When we have the certificate, you can store in one or more ways to make it
accessible to your applications. The Windows Certificate Store is the default
location for IIS (unless you are managing a cluster of them).

1: IIS Central Certificate Store (.pfx per host)
2: PEM encoded files (Apache, nginx, etc.)
3: PFX archive
4: Windows Certificate Store (Local Computer)
5: No (additional) store steps

How would you like to store the certificate?: 2
  • 证书类型,因为我们是为nginx申请证书,所以选择第二种。
1
2
3
Description:        .pem files are exported to this folder.

File path: C:\APP\ssl
  • 证书保存地址
1
2
3
4
5
6
7
Description:        Password to set for the private key .pem file.

1: None
2: Type/paste in console
3: Search in vault

Choose from the menu: 1
  • 私钥是否设置密码,这里选择None,不设置。

之后的很多操作,直接选择默认值即可。

Ubuntu

Ubuntu 使用certbot申请证书,同样基于 Let’s Encrypt,免费。

需要提前启动nginx,原因与Windows版本相同:certbot 需要通过本地文件的方式验证域名所有权。

安装certbot

1
sudo apt install certbot -y

申请证书:

1
2
3
sudo certbot certonly --webroot \
-w /var/www/html \
-d 【域名】

按提示输入邮箱、同意条款即可。

证书申请成功后,保存在:

1
2
/etc/letsencrypt/live/【域名】/fullchain.pem   # 对应 Windows 版的 chain.pem
/etc/letsencrypt/live/【域名】/privkey.pem # 对应 Windows 版的 key.pem

certbot 默认已安装 systemd 定时任务,证书到期前会自动续期。可通过以下命令验证续期是否正常:

1
sudo certbot renew --dry-run

证书配置

Windows

通过上述步骤,我们会得到如下四个文件。

  • chain.pem
  • chain-only.pem
  • crt.pem
  • key.pem

我们需要的是chain.pemkey.pem

修改nginx的confnginx.conf文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
worker_processes  1;
events {
worker_connections 1024;
}
http {
server {
listen 443 ssl http2;

server_name 【域名】;
ssl_certificate 【chain.pem的绝对路径】;
ssl_certificate_key 【key.pem的绝对路径】;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

location / {
proxy_pass https://【被反代的域名】;
proxy_ssl_server_name on;
proxy_redirect off;
sub_filter_once off;
sub_filter "【被反代的域名】" $server_name;
proxy_set_header Host "【被反代的域名】";
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language "zh-CN";
}


location /r {
proxy_redirect off;
proxy_pass http://127.0.0.1:【端口】;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80;

location /.well-known/ {
root html;
}
location / {
rewrite ^(.*)$ https://$host$1 permanent;
}
}

}

Ubuntu

Ubuntu 下 nginx 通过apt安装,自带完整的默认配置,需要在此基础上修改/etc/nginx/nginx.conf

与 Windows 版相比,主要差异有两点:

  • 证书路径改为 certbot 生成的路径
  • 保留 Ubuntu 默认配置中的userpidmime.types等系统相关项

完整的nginx.conf如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 1024;
}

http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log /var/log/nginx/access.log;

gzip on;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

server {
listen 443 ssl http2;
server_name 【域名】;

ssl_certificate /etc/letsencrypt/live/【域名】/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/【域名】/privkey.pem;

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

location / {
proxy_pass https://【被反代的域名】;
proxy_ssl_server_name on;
proxy_redirect off;
sub_filter_once off;
sub_filter "【被反代的域名】" $server_name;
proxy_set_header Host "【被反代的域名】";
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language "zh-CN";
}

location /r {
proxy_redirect off;
proxy_pass http://127.0.0.1:【端口】;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

server {
listen 80;
server_name 【域名】;

location /.well-known/ {
root /var/www/html;
}

location / {
rewrite ^(.*)$ https://$host$1 permanent;
}
}
}

修改完成后,验证语法并重载:

1
2
sudo nginx -t
sudo systemctl reload nginx

V2

Github地址:

Github地址

一键安装脚本:

一键安装脚本

服务端配置,config.json

V2-服务端

启动 V2 并设置开机自启:

V2-服务端

移动设备客户端配置:

V2-客户端-1

解释说明:

  • 服务端配置的ws对应客户端配置的websocket
  • 服务端配置的/r对应客户端配置的/r,对应nginx配置的location /r
  • 服务端配置的listenport对应nginx的location /rproxy_pass
  • TLS可能需要选择开启。

PC设备客户端配置:
Profiles页面,导入我们新建的.yaml文件,内容如下:

V2-客户端-2

文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/19907
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

留言板