OVH多IP服务器中Plesk域名出站请求源IP与分配IP不符问题求助
我来帮你捋捋这个问题——这事儿其实是Linux系统默认的路由策略在搞鬼:系统会自动选择每个子网路由条目里src指定的主IP(也就是你路由表中a.b.c.0/24段的a.b.c.161)作为出站请求的源IP,完全不管Plesk给域名分配的是同子网里的哪个附加IP。下面给你几个实用的解决办法,按需选就行:
方法一:给每个附加IP配置专属路由策略(最彻底的系统级方案)
这个方法能让所有从指定IP发起的请求(不管是PHP脚本、cron任务还是其他进程),出站时都用这个IP本身,而不是子网主IP。步骤如下:
先查看当前可用的路由表编号,执行命令:
cat /etc/iproute2/rt_tables找一个没被占用的编号(比如100、101这类,别用已有的)。
给目标IP(比如你提到的a.b.c.162)添加专属路由表:
echo "100 rt_abcc162" >> /etc/iproute2/rt_tables这里的
rt_abcc162是自定义的表名,方便识别就行。给这个路由表配置子网和默认路由(注意替换成你实际的子网网关,OVH的子网网关一般是子网最后一位254,比如a.b.c.254):
ip route add a.b.c.0/24 dev eno0 src a.b.c.162 table rt_abcc162 ip route add default via a.b.c.254 dev eno0 src a.b.c.162 table rt_abcc162添加路由规则,让从a.b.c.162发出的请求强制使用这个专属表:
ip rule add from a.b.c.162 table rt_abcc162 ip rule add to a.b.c.162 table rt_abcc162保存配置避免重启失效:你可以把上述
ip route和ip rule命令写入/etc/rc.local(如果系统支持),或者创建一个systemd服务来自动加载,也可以用ip route save > /etc/iproute2/ip_routes和ip rule save > /etc/iproute2/ip_rules来保存规则(不同系统可能略有差异,需要测试)。
方法二:用iptables NAT规则定向替换源IP(快速适配特定场景)
如果不想折腾路由表,也可以用iptables的SNAT规则,把特定进程或IP的出站请求源IP替换成你想要的那个。比如:
如果你知道该域名对应的PHP-FPM进程用户ID(Plesk里每个域名一般有专属的系统用户),可以这样写:
iptables -t nat -A POSTROUTING -m owner --uid-owner [域名对应的用户UID] -j SNAT --to-source a.b.c.162要找UID的话,可以用
id [用户名]命令查看。要是想针对整个a.b.c.162的出站请求都替换,直接写:
iptables -t nat -A POSTROUTING -s a.b.c.162 -j SNAT --to-source a.b.c.162
记得用iptables-save > /etc/iptables/rules.v4(Debian/Ubuntu)或者service iptables save(CentOS)来保存规则,防止重启丢失。
方法三:针对PHP脚本单独配置(仅限PHP场景)
如果问题只出在PHP后端的出站请求,你可以在Plesk里给对应域名的PHP-FPM池加配置,强制脚本使用指定IP:
- 登录Plesk面板,找到目标域名,进入「PHP设置」
- 找到「附加配置指令」,添加以下内容(替换成你的IP):
然后在PHP脚本里,发起请求时手动指定这个源IP(比如用env[SOURCE_IP] = a.b.c.162curl的--interface参数,或者stream_context_create设置bindto选项):$context = stream_context_create([ 'socket' => [ 'bindto' => 'a.b.c.162:0' ] ]); $response = file_get_contents('https://example.com', false, $context);
这个方法需要修改脚本,适合只需要调整PHP请求的场景。
备注:内容来源于stack exchange,提问作者Shreef Entsar




