域主终于把内网搭建的景の域通过FRP穿透出来了!博客总算重见天日~
这次发一下搭建FRP穿透内网WP博客的记录……
关于FRP的简短介绍,详见之前搭建FRP的日记:搭建FRP服务端的一次吃瓜日记
初次实践
我的内网Web服务器是一个PVE中运行的虚拟机,使用Webinoly搭建基于Nginx的vhost虚拟主机;FRP的客户端frpc在OpenWRT的虚拟机安装运行;在公网的VPS搭建FRP服务端frps和Webinoly(只安装Nginx服务)
*实际上PVE在整个穿透过程中的存在感极低,去掉虚拟化不过就是同一局域网段下的两台机器,甚至完全可以把frpc和Nginx放在一起部署……
最开始我在内网的Webinoly部署了SSL证书,frps直接设置为443端口的https隧道转发到公网VPS,在内网Nginx网站conf的端口访问打开proxy_protocol协议透传IP访问
这样SSL由内网Nginx处理,FRP仅处理流量的转发工作。连接流程是这样的:
访客 → 公网frps https (443) → 内网frpc 转发 Nginx https (443 SSL)
这么做有两个弊端,不能走Cloudflare的CDN或其他服务器中转,只要加上CDN就无法访问了;此外公网VPS的IP访问也是暴露的(不能设置SSL reject handshake (444) 黑洞),不算非常安全。
后面我尝试了在公网VPS加上用Webinoly搭建的Nginx,将frp的https端口设置为8443,然后再对frp转发反向代理,实现443的端口复用(这样就可以设置黑洞了)
访客 → 公网Nginx https (443) 转发 frps https (8443) → 内网 frpc 转发 Nginx https (443 SSL)
然而这样就出现502或者无限重定向的问题了,原因是https证书的请求头(headers)改变了,相当于中间人介入,无论使用CF还是直连都不可行。而且网上很多Nginx复用frp的教程都是转发http的。
用TCP模式+upstream上游监听理论上能解决问题,然而由于我的内网Nginx服务端的IP访问配置了SSL黑洞,也就是上文提到基于域名判断的vhost模式,这个方案还是行不通。
正因为https的转发问题,让我熬夜研究了整整两天,差点猝死()
更换思路
既然不能直接转发内网https协议处理,那就换成转发内网http的流量经由Nginx端口复用,让公网VPS上的Nginx处理SSL?这样还能用Webinoly的certbot管理证书更新。实际搭建好以后还可以打开CDN,完全可以用CF的15年证书。
此时流程变成了这样:
访客 → (CF CDN)公网Nginx https (443 SSL) 转发 frps http (8080) → 内网frpc 转发 Nginx http (80)
*frp隧道之间可通过tls加密安全传输流量
那么配置方式就变成了,在公网的VPS用Webinoly新建网站并配置SSL,而内网的Webinoly关闭SSL,保持http协议访问。即为https2http模式。
在公网Nginx的网站conf配置加入以下代码(Webinoly配置的Nginx是在#WebinolyCustomStart行下面)
location / {
proxy_pass http://127.0.0.1:8080;
proxy_ssl_server_name on;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
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_redirect http:// $scheme://;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}
内网的Nginx网站配置,直接在80后面添加 proxy_protocol 就可以:
# WebinolyNginxServerStart
server {
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
如果用的是Webinoly还需要注释默认的全局locations和headers配置链接:
#include common/locations.conf;
#include common/headers.conf;
但如果要穿透基于WordPress的博客、获得访客的真实IP,还是需要做一些微小的工作滴(否则连评论的IP记录都会变成192.168.*.*或者127.0.0.1的本地地址)
在wp-config添加一些代码,让WP在数据库层面启用https跳转资源和FRP穿透与CDN的标头转发记录:
/* Add any custom values between this line and the "stop editing" line. */
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS']='on';
if( !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
$get_HTTP_X_FORWARDED_FOR = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = trim($get_HTTP_X_FORWARDED_FOR[0]);
}
这时候再访问站点的主页,资源文件,如CSS样式都能够正常访问了。
实际搭建好以后感觉速度变慢了好多,毕竟家宽只有30M的上行(而且有时候我回家用RDP的话还会抢占带宽),境内外来回转去延迟也不如DDNS的说
嘛,好处是降低了租用服务器的成本,这三年的VPS反倒涨价了不少,也不送快照备份了……