nginx反向代理frp缓存加速

背景描述

由于frp的http和https,都是从用户的服务中完整输出数据的,这对于一些使用frp的用户,网络比较差/上传低,打开自己的这些服务,要加载大半天的。
我们可以使用nginx的反代缓存,把frp用户的http和https中的静态资源缓存到服务器本地,从而减少frp用户本身的网络资源请求访问,直接略过大部分,从而在服务器加速。
效果是拔群的!

nginx反向代理缓存配置

本例编译安装nginx,安装路径为/app/nginx
新建缓存目录
mkdir -pv /app/nginx/cache
赋予权限
chmod -R 775 /app/nginx/cache
修改nginx.conf
vim /app/nginx/conf/nginx.conf
在http{}模块里面添加

1
include  extra/*.conf;

新建vhost.conf:
vim /app/nginx/conf/extra/vhost.conf
我的配置文件如下,含多个https:

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
proxy_cache_path /app/nginx/cache levels=1:2 keys_zone=frp_cache:100m max_size=5g inactive=30d;
resolver 8.8.8.8;
server {
listen 80;
server_name *.xxx.com;

#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;

location / {
proxy_pass http://127.0.0.1:8680;
proxy_redirect http://$host/ http://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}

location ~* \.(jpg|jpeg|gif|png|svg|css|scss|js|ico|xml|woff|woff2|ttf|otf|eot)$ {
proxy_pass http://127.0.0.1:8680;
proxy_redirect http://$host/ http://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_cache frp_cache;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 206 301 302 304 3d;
expires 30d;
add_header X-Cache '$upstream_cache_status from $host';
}
}

server{
listen 443 ssl;
#ssl on;
server_name a.xxx.com;
ssl_certificate /app/cert/esxi.hellshan.top.pem;
ssl_certificate_key /app/cert/esxi.hellshan.top.key;
#ssl_trusted_certificate /app/cert/ca.cer;

location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass https://$host:4443; #通过域名访问frp服务
}

location ~* \.(jpg|jpeg|gif|png|svg|css|scss|js|ico|xml|woff|woff2|ttf|otf|eot)$ {
proxy_ssl_server_name on;
proxy_pass https://$host:8643; #通过域名访问frp服务
proxy_redirect https://$host/ https://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-proto https;
proxy_cache frp_cache;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 206 301 302 304 3d;
expires 30d;
add_header X-Cache '$upstream_cache_status from $host';
}
}

server{
listen 443 ssl;
#ssl on;
server_name b.xxx.com;
ssl_certificate /app/cert/cloud.hellshan.top.pem;
ssl_certificate_key /app/cert/cloud.hellshan.top.key;
#ssl_trusted_certificate /app/cert/ca.cer;

location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass https://$host:8643; #通过域名访问frp服务
}

location ~* \.(jpg|jpeg|gif|png|svg|css|scss|js|ico|xml|woff|woff2|ttf|otf|eot)$ {
proxy_ssl_server_name on;
proxy_pass https://$host:8643; #通过域名访问frp服务
proxy_redirect https://$host/ https://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-proto https;
proxy_cache frp_cache;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 206 301 302 304 3d;
expires 30d;
add_header X-Cache '$upstream_cache_status from $host';
}
}

配置说明

(jpg|jpeg|gif|png|svg|css|scss|js|ico|xml|woff|woff2|ttf|otf|eot)为需要进行缓存的静态资源,你可以添加或者修改。

proxy_cache_valid为服务器缓存,其中200 206 301 302 304为HTTP状态码(http://tool.chinaz.com/pagestatus/
针对状态码缓存,而最后面的 30d 为缓存过期时间,当用户没有在这个有效时间内访问到这个资源,则会过期清除,直到用户重新访问到这个资源则重新缓存。
expires 为访问用户本地缓存
d 天数 h 小时 m 分钟 s 秒

http://127.0.0.1:8680的8080端口为你frp.ini配置文件vhost_http_port = 8680端口
http://127.0.0.1:8643 的8643端口为你frp.ini配置文件vhost_https_port = 8643端口
对应的frps.ini配置如下:

1
2
vhost_http_port = 8680
vhost_https_port = 8643

其中的端口可以根据自己的需要修改。

配置成功后,并且访问目标网站,让nginx进行缓存,在/home/nginx/cache目录里会生成多个缓存目录和文件。

对于nginx https代理frp https的理解

我的理解是这样的:
如果使用了自定义域名,frp是根据$host值判断该往哪个内网服务转发请求的,因此转给frp的请求中一定要包含$host,否则frp无法正常处理请求。
因此以下2个配置很重要:

1
2
proxy_ssl_server_name on;
proxy_pass https://$host:8643; #通过域名访问frp服务

proxy_pass中不能写成IP的形式。
举一个我的例子,我内网服务器10.1.1.8上部署着2个服务,elasticsearch和kibana,端口分别是9200和5601,我现在想要把这2个服务穿透出去,具体配置如下:
frps.ini中的主要配置:
xxx替换成自己的

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
[common]
bind_addr = 0.0.0.0
bind_port = 7000
bind_udp_port = 7001
kcp_bind_port = 7000
vhost_http_port = 8680
vhost_https_port = 8643
dashboard_addr = 0.0.0.0
dashboard_port = 7xxx
dashboard_user = xxx
dashboard_pwd = xxx
enable_prometheus = true
log_file = /app/frp/frps.log
log_level = info
log_max_days = 3
disable_log_color = false
detailed_errors_to_client = true
authentication_method = token
authenticate_heartbeats = false
authenticate_new_work_conns = false
token = hellshan.top
oidc_client_id =
oidc_client_secret =
oidc_audience =
oidc_token_endpoint_url =
allow_ports = 1-65535
max_pool_count = 5
max_ports_per_client = 0
tls_only = false
subdomain_host = hellshan.top
tcp_mux = true

然后通过上边配置的nginx进行代理转发请求到frp上。
frpc.ini的配置如下:

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
75
76
77
78
79
80
81
[common]
server_addr = hellshan.top
server_port = 7000
protocal = kcp
token = hellshan.top

[k3_web_control]
type = http
local_ip = 10.1.1.1
local_port = 80
subdomain = k3
use_encryption = false
use_compression = false

[server2019_remote_control]
type = tcp
local_ip = 10.1.1.11
local_port = 3389
remote_port = 42264
subdomain = remote
use_encryption = true
use_compression = false

[pve_web_control]
type = https
local_ip = 10.1.1.8
local_port = 8006
subdomain = esxi
use_encryption = false
use_compression = false

[pve_ssh_control]
type = tcp
local_ip = 10.1.1.8
local_port = 22
remote_port = 22222
subdomain = ssh
use_encryption = false
use_compression = false

[monitor_web_control]
type = http
local_ip = 10.1.1.12
local_port = 80
subdomain = monitor
use_encryption = false
use_compression = false

[monitor_tcp_port]
type = tcp
local_ip = 10.1.1.12
local_port = 10051
remote_port = 10051
subdomain = monitor
use_encryption = false
use_compression = false

[kibana_web_congrol]
type = http
local_ip = 10.1.1.13
local_port = 5601
subdomain = kibana
use_encryption = false
use_compression = false

[elastics_web_congrol]
type = http
local_ip = 10.1.1.13
local_port = 9200
subdomain = elastics
use_encryption = false
use_compression = false

[portainer_web_control]
type = http
local_ip = 10.1.1.8
local_port = 9000
subdomain = docker
use_encryption = false
use_compression = false

http强制跳转到https

frp支持从http转为https,详细可以参考https://github.com/fatedier/frp#enable-https-for-local-http-service配置,因为我是用路由器作为frpc,而frpc需要添加证书目录才能生效,不好操作,故使用强大的Nginx来实现,在nginx的云主机上统一存放证书。
例:

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
#=============================== for docker.hellshan.top ======================================

server {
listen 80;
server_name docker.hellshan.top;
rewrite ^(.*) https://$server_name$1 permanent;
}

server{
listen 443 ssl;
server_name docker.hellshan.top;
ssl_certificate /app/cert/docker.hellshan.top.pem;
ssl_certificate_key /app/cert/docker.hellshan.top.key;

location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass http://$host:8680;
}

location ~* \.(jpg|jpeg|gif|png|svg|css|scss|js|ico|xml|woff|woff2|ttf|otf|eot)$ {
proxy_ssl_server_name on;
proxy_pass http://$host:8680;
proxy_redirect http://$host/ http://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-proto https;
proxy_cache frp_cache;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 206 301 302 304 3d;
expires 30d;
add_header X-Cache '$upstream_cache_status from $host';
}
}

这里配置了两个server来实现跳转,http部分使用rewrite ^(.*) https://$server_name$1 permanent;作为重定向,然后下面跟https的配置,而下面的proxy_pass则要配置成http的,因为实际上是走http的协议,这样访问域名的时候,就会跳转到https。

部分转载自:http://www.wangxianfeng.cn/wordpress/2018/06/10/nginx%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86frp%E7%BC%93%E5%AD%98%E5%8A%A0%E9%80%9Fhttphttps/

分享到