利用Nginx与frp内网穿透搭建WordPress并获取访客真实IP

0. 前言

2022年底,本站正式迁移至国产平台龙芯3A5000。
但由于家用宽带禁止开启80/443端口,需要一台公网VPS做反向代理。
同时,为了防止垃圾评论信息,需要获取访客的真实IP以建立黑名单。

整体架构:
公网VPS → Nginx → frps → 内网服务器 → frpc → Nginx → WordPress (php)

1. 公网VPS配置

nginx

在vhost的配置文件中添加:

location / {
    proxy_pass https://127.0.0.1:<frpc监听端口>/;
    proxy_redirect off;

    proxy_set_header Host host;
    proxy_set_header X-Real-IPremote_addr;
    proxy_set_header X-Forwarded-Host server_name;
    proxy_set_header X-Forwarded-Forproxy_add_x_forwarded_for;
}

frps

[common]
bind_port = <frps监听端口>

tcp_mux = true
tls_enable = true
tls_only = true

authentication_method = token
token = <token>

# trace, debug, info, warn, error
log_level = info
log_max_days = 3
log_file = /etc/frp/frps.log

2. 内网服务器配置

nginx

将vhost中的server设置为:

listen <frpc监听端口> ssl http2 proxy_protocol;

并添加:

real_ip_header proxy_protocol;
real_ip_recursive on;
set_real_ip_from 127.0.0.1;

frpc

[common]
server_addr = <frps公网ip>
server_port = <frps监听端口>

tcp_mux = true
tls_enable = true

authentication_method = token
token = <token>

# trace, debug, info, warn, error
log_level = debug
log_max_days = 3
log_file = /etc/frp/frpc.log

[katyusha.net]
type = tcp
local_ip = 127.0.0.1
local_port = <frpc监听端口>
remote_port = <frpc监听端口>
proxy_protocol_version = v2

3. WordPress 获取反代后的真实ip

在wp-config.php文件末尾添加:

/*获取反代后的真实IP*/
if ( !empty( _SERVER[_!_!_039;HTTP_CLIENT_IP_!_!_039;] ) ) { //check ip from share internetip = _SERVER[_!_!_039;HTTP_CLIENT_IP_!_!_039;];
} elseif ( !empty(_SERVER[_!_!_039;HTTP_X_REAL_IP_!_!_039;] ) ) {
    ip =_SERVER[_!_!_039;HTTP_X_REAL_IP_!_!_039;];
} elseif ( !empty( _SERVER[_!_!_039;HTTP_X_FORWARDED_FOR_!_!_039;] ) ) {ip = _SERVER[_!_!_039;HTTP_X_FORWARDED_FOR_!_!_039;];
} else {ip = _SERVER[_!_!_039;REMOTE_ADDR_!_!_039;];
}_SERVER[_!_!_039;REMOTE_ADDR_!_!_039;] = $ip; // set ip via complex method because remote_addr could have proxy ip

/*设置服务端真实端口*/
#define( _!_!_039;JETPACK_SIGNATURE__HTTPS_PORT_!_!_039;, <frpc监听端口> )

4. 测试

可创建一个php文件,用于测试是否能获取到真实ip

<p>REMOTE_ADDR: <?php function get_REMOTE_ADDR(){
    return @_SERVER["REMOTE_ADDR"];
}
echo get_REMOTE_ADDR();
?></p>
<br/>
<p>HTTP_X_REAL_IP: <?php function get_HTTP_X_REAL_IP(){
    return @_SERVER["HTTP_X_REAL_IP"];
}
echo get_HTTP_X_REAL_IP();
?></p>
<br/>
<p>HTTP_X_FORWARDED_FOR: <?php function get_HTTP_X_FORWARDED_FOR(){
    return @_SERVER["HTTP_X_FORWARDED_FOR"];
}
echo get_HTTP_X_FORWARDED_FOR();
?></p>
<br/>
<p>HTTP_CLIENT_IP: <?php function get_HTTP_CLIENT_IP(){
    return @_SERVER["HTTP_CLIENT_IP"];
}
echo get_HTTP_CLIENT_IP();
?></p>

2 Comments

  1. 终于看到一篇文章说这类文章了。
    但是你这个是通过反向代理实现真实IP的。
    而我注意到你用到了proxy_protocol协议,反向代理和这个二者选一就可以了。反向代理我懂了,我的网站也是这样实现的。但是如果用proxy_protocol这个协议就行不通,首先开启proxy_protocol解析(listen ssl http2 proxy_protocol;),网站就打不开了。
    请劳烦帮我解此疑惑?万分感谢!

    1. 不好意思,我没有遇到过这样的情况。也许可以检查一下你的nginx版本?

发表回复

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