FRP+Nginx+Cloudflare CDN穿透内网WordPress博客小记

域主终于把内网搭建的景の域通过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反倒涨价了不少,也不送快照备份了……

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注