You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OVH多IP服务器中Plesk域名出站请求源IP与分配IP不符问题求助

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。步骤如下:

  1. 先查看当前可用的路由表编号,执行命令:

    cat /etc/iproute2/rt_tables
    

    找一个没被占用的编号(比如100、101这类,别用已有的)。

  2. 给目标IP(比如你提到的a.b.c.162)添加专属路由表:

    echo "100 rt_abcc162" >> /etc/iproute2/rt_tables
    

    这里的rt_abcc162是自定义的表名,方便识别就行。

  3. 给这个路由表配置子网和默认路由(注意替换成你实际的子网网关,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
    
  4. 添加路由规则,让从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
    
  5. 保存配置避免重启失效:你可以把上述ip routeip rule命令写入/etc/rc.local(如果系统支持),或者创建一个systemd服务来自动加载,也可以用ip route save > /etc/iproute2/ip_routesip 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:

  1. 登录Plesk面板,找到目标域名,进入「PHP设置」
  2. 找到「附加配置指令」,添加以下内容(替换成你的IP):
    env[SOURCE_IP] = a.b.c.162
    
    然后在PHP脚本里,发起请求时手动指定这个源IP(比如用curl--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

火山引擎 最新活动