解决 Nginx + Frp 实现 HTTP 服务穿透时"窜站"的问题

657

环境配置

  • Frp服务端配置vhost_http_port,subdomain_host属性项,设置HTTP访问端口和子域名
...
vhost_http_port = 65535
subdomain_host = frp.xxx.cn
...
  • Nginx配置server监听80端口,使Frp配置的subdomain_host的泛域名反向代理到vhost_http_port配置的端口
server {
	listen 80;
	server_name *.frp.xxx.cn;
	location / {
		proxy_pass http://127.0.0.1:65535;
		...
	}
	...
}

主要问题

  • Frp客户端配置多个vhost服务时,访问不同子域站点会出现"窜站"的问题:访问不同子域站点的域名时,只返回其中一个vhost服务的页面,但仅是静态资源能被正常加载,XHR资源则是使用正确的子域站点域名访问时会被正确加载

寻找原因

  1. 怀疑是前端缓存导致,清除浏览器缓存后再次使用访问,或使用curl访问,静态资源仍正常返回,HTTP状态码为200
  2. 将Frp服务Down掉后,使用浏览器仍然能访问到静态资源,怀疑为Nginx配置了静态资源缓存
  3. 检查Nginx配置文件,发现在http层级include一个conf配置,如下
proxy_temp_path /www/server/nginx/proxy_temp_dir;
proxy_cache_path /www/server/nginx/proxy_cache_dir levels=1:2 keys_zone=cache_one:20m inactive=1d max_size=5g;
client_body_buffer_size 512k;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_buffer_size 32k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
proxy_cache cache_one;
  1. 检查proxy_cache_path目录发现被Nginx缓存的静态资源文件
  2. 由此得知,HTTP请求到达Nginx和Frp经过了两次反向代理,因为只配置了一个server层级和全局缓存,Nginx为泛域名指向同一站点并缓存静态资源,所以导致窜站

解决方案

  • 方法一:删除全局缓存配置
  • 方法二:保留全局缓存配置,增加 proxy_cache off 配置项,单独关闭反代Frp服务的server的缓存
server {
	listen 80;
	server_name *.frp.xxx.cn;
	location / {
		proxy_pass http://127.0.0.1:65535;
		proxy_cache off;
		...
	}
	...
}