You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nginx中为每个域名分配不同的IPv6地址?

如何在Nginx中为每个域名分配不同的IPv6地址?

看起来你已经给每个域名在Nginx里指定了专属的IPv6监听地址,也配置好了DNS的AAAA记录,但遇到了出站请求(比如PHP的curl调用)总是用系统默认IPv6的问题——这是因为Linux默认会选网卡上的“主”IPv6作为所有出站流量的源地址,不管Nginx监听的是哪个IP。下面分两步帮你解决:

一、先确认系统已加载所有需要的IPv6地址

首先得确保服务器系统上真的配置了所有你要用到的IPv6,而不只是在控制面板里添加了。登录服务器执行命令:

ip -6 addr show

检查输出里有没有你给各个域名分配的IPv6(比如79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60)。如果某个IP没出现,就得手动在系统里配置:
Ubuntu 22.04用Netplan管理网络,编辑/etc/netplan/00-installer-config.yaml(文件名可能不同,找你的Netplan配置文件),添加额外IPv6:

network:
  ethernets:
    ens3: # 替换成你的网卡名,用`ip link show`查看
      addresses:
        - 你的主IPv6/64
        - 79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60/64
        - 其他需要的IPv6/64
      gateway6: 你的IPv6网关(通常是子网第一个IP,比如xxxx:xxxx:xxxx:xxxx::1)
      nameservers:
        addresses: [2606:4700:4700::1111, 2001:4860:4860::8888]
  version: 2

执行netplan apply让配置生效,再用ip -6 addr show确认所有IP都已加载。

二、解决PHP出站请求的源IP问题

方法1:在PHP代码中指定源IP(简单直接)

这种方法适合只需要调整curl请求的场景。你可以在Nginx里给每个域名传递对应的IPv6,再让curl用这个IP作为源地址。

  1. 修改Nginx的server配置,添加fastcgi_param传递IP:
server {
    listen [79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60]:80;
    server_name sub.domain.com www.sub.domain.com;

    # 新增这行,把当前域名的IPv6传给PHP
    fastcgi_param PHP_SOURCE_IP "79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60";

    access_log /var/log/nginx/sub.domain.com.access.log rt_cache;
    error_log /var/log/nginx/sub.domain.com.error.log;

    root /var/www/sub.domain.com/htdocs;
    index index.php index.html index.htm;

    include common/php81.conf;
    include common/locations-wo.conf;
    include /var/www/sub.domain.com/conf/nginx/*.conf;
}
  1. 修改PHP代码,让curl使用指定的源IP:
<?php
// 获取Nginx传递的IPv6地址
$sourceIp = $_SERVER['PHP_SOURCE_IP'] ?? '';

// 创建cURL资源
$ch = curl_init();

// 设置检测公网IP的目标URL
curl_setopt($ch, CURLOPT_URL, "https://ipv6.icanhazip.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// 强制用IPv6,并指定源IP
if (!empty($sourceIp)) {
    curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
    curl_setopt($ch, CURLOPT_INTERFACE, $sourceIp);
}

// 执行请求并输出结果
$result = curl_exec($ch);
curl_close($ch);

echo "当前出站IPv6:" . $result;
?>

修改后重启服务:

systemctl restart nginx
systemctl restart php8.1-fpm

现在访问这个PHP文件,应该会显示当前域名对应的IPv6了。

方法2:为每个域名创建独立PHP-FPM池(全站流量用对应IP)

如果你的网站有很多出站请求(不止curl),想让整个域名的PHP进程都用指定IPv6,可以给每个域名单独建PHP-FPM池,再配置路由规则绑定IP。

  1. 创建新的FPM池配置文件,比如/etc/php/8.1/fpm/pool.d/sub.domain.com.conf:
[sub.domain.com]
listen = /run/php/php8.1-fpm-sub.domain.com.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

user = www-data
group = www-data

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

env[PATH] = /usr/local/bin:/usr/bin:/bin
  1. 修改Nginx的server块,让它使用这个新FPM池:
    在当前server块里覆盖默认的FPM sock路径:
server {
    listen [79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60]:80;
    server_name sub.domain.com www.sub.domain.com;

    # 替换成新的FPM sock
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.1-fpm-sub.domain.com.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    # 其他原有配置...
}
  1. 配置路由规则,绑定FPM池到指定IPv6:
    先创建新路由表并添加默认路由:
echo "100 subdomain" >> /etc/iproute2/rt_tables
ip -6 route add default via 你的IPv6网关 src 79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60 table 100

再添加规则,让这个FPM池的进程(属于www-data用户)用这个路由表:

ip -6 rule add uidrange www-data-www-data lookup 100

为了让配置重启后生效,把命令加到/etc/rc.local(没有就创建,记得加执行权限chmod +x /etc/rc.local):

#!/bin/bash
ip -6 route add default via 你的IPv6网关 src 79de:d3e4:211c:3963:e2d5:4b9d:00b8:2c60 table 100
ip -6 rule add uidrange www-data-www-data lookup 100
exit 0

最后重启服务:

systemctl restart php8.1-fpm
systemctl restart nginx

这样这个域名下所有PHP进程的出站请求,都会用指定的IPv6地址。

备注:内容来源于stack exchange,提问作者TravelWhere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 09:44:52