你买多 IP VPS 的原因通常很朴素:
- 同一台机器跑多个站点,希望“站 A/站 B”各自一个独立 IP
- 做邮件服务器,需要干净 IP + 能配 PTR(反向解析)
- 做爬虫/接口请求,想分散出站 IP
- 你不想每次都解释“这几个业务其实在同一台 VPS 上”
但多 IP 最烦的点也很统一:
- 副 IP 加上去了,外面还是 ping 不通
- 出站永远走主 IP(你明明想用副 IP)
- Nginx 只在 IPv4 某个 IP 上监听,另一个 IP 访问超时
这篇文章我按“能落地”为目标写:你照着做,能把副 IP 配通、能持久化、能控制出站源地址。
商家给多 IP 通常有两种形态:
- 附加单个 IPv4(/32)
- 你会拿到:一个额外 IPv4 + 说明“加到 eth0 上”
- 整段子网(/29、/28)路由到你
- 你会拿到:一段公网子网 + 网关/路由说明
这两种配置方式有共通点,但“出站选源 IP”和“路由表”处理会有差异。
你可以先把你现在的网络状态打出来:
ip -4 addr
ip -4 route
重点看两件事:
- 主 IP 是怎么配的(是 DHCP 还是 static)
- 默认路由的网关是多少
假设你拿到的副 IP 是 203.0.113.10/32,网卡是 eth0。
sudo ip addr add 203.0.113.10/32 dev eth0
ip -4 addr show dev eth0
这一步只是“把 IP 挂到网卡上”,不会改你的默认路由。
从 VPS 自己验证出站:
curl -4 -s https://api.ipify.org && echo
再验证“指定源地址出站”(这一步很关键):
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
- 如果第二条也能返回
203.0.113.10:说明你的副 IP 至少能出站 - 如果报错(比如
Cannot assign requested address/ 超时):说明副 IP 还没真正可用,别急着写配置文件
很多商家给的 IP 是“路由到你”的,入站能不能通跟你本机防火墙/服务监听也有关。先把出站跑通,心态会稳很多。
你系统属于哪一类,通常看这三条:
ls -l /etc/netplan/ 2>/dev/null || true
ls -l /etc/network/interfaces 2>/dev/null || true
nmcli -v 2>/dev/null || true
打开现有配置(文件名可能不同):
sudo ls -l /etc/netplan/
sudo cat /etc/netplan/*.yaml
在 addresses: 里把副 IP 加进去(示例):
network:
version: 2
ethernets:
eth0:
dhcp4: true
addresses:
- 203.0.113.10/32
应用:
sudo netplan apply
你可以用最稳的 post-up 写法(避免改你主 IP 的方式):
auto eth0
iface eth0 inet dhcp
# add extra IPv4
post-up ip addr add 203.0.113.10/32 dev eth0 || true
pre-down ip addr del 203.0.113.10/32 dev eth0 || true
重启网络:
sudo systemctl restart networking
# 先找到连接名
nmcli con show
# 假设连接名是 "System eth0"
sudo nmcli con mod "System eth0" +ipv4.addresses "203.0.113.10/32"
sudo nmcli con up "System eth0"
比如 Nginx 你只写了:
listen 80;
那它可能只监听 0.0.0.0:80(通常没问题),但你如果写了特定 IP,就要确保两个都写。
示例:让站点同时在主 IP + 副 IP 上可访问:
server {
listen 203.0.113.1:80;
listen 203.0.113.10:80;
server_name example.com;
location / { return 200 "ok\n"; }
}
重载:
sudo nginx -t
sudo systemctl reload nginx
最简单的自检:
sudo ss -lntp | head
确认服务在监听,再去看防火墙规则。
如果你之前还没做过基础加固,建议先把这篇过一遍(别把多 IP 玩成“多入口被扫”):
这是“多 IP 最真实的坑”。
解决方式有两个层级:
- 简单粗暴:让程序自己绑定源地址(能解决 80% 的需求)
- 更通用:用策略路由,让“从某个 IP 出去”的流量走一套路由表
下面两节分别讲。
很多服务/工具都支持绑定源地址。
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
ssh -b 203.0.113.10 user@target-host
- Nginx 反代上游时可以绑源 IP
- 你的程序(Go/Node/Python)发起请求时也可以 bind local address
只要你能在应用层绑定,基本就不需要动策略路由。
适用场景:你不想每个程序都手动 bind,或者你想把某个 IP 作为“专用出站 IP”。
假设:
- 主 IP:
203.0.113.1 - 副 IP:
203.0.113.10 - 默认网关:
203.0.113.254 - 网卡:
eth0
ip -4 route show dev eth0 scope link
你会看到类似:
203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.1
记住这个网段(比如 203.0.113.0/24)。
# 1) 新建路由表
sudo bash -lc 'echo "100 out-ip2" >> /etc/iproute2/rt_tables'
# 2) 给新表加直连网段(让它能到网关)
sudo ip route add 203.0.113.0/24 dev eth0 scope link table out-ip2
# 3) 新表默认路由,指定 src
sudo ip route add default via 203.0.113.254 dev eth0 src 203.0.113.10 table out-ip2
# 4) 规则:从 203.0.113.10 发出的流量走 out-ip2 表
sudo ip rule add from 203.0.113.10/32 table out-ip2
# 查看
ip rule
ip route show table out-ip2
验证:
curl -4 --interface 203.0.113.10 -s https://api.ipify.org && echo
注意:不同商家的网关/网段可能不是上面的形式。你只要按“把 scope link 那条也写进新表”的思路做,基本就能通。
这块各发行版差异很大。
- 你可以先用“启动脚本 + systemd service”的方式持久化(最不容易被 netplan/cloud-init 覆盖)
- 或者按发行版把规则写进 network hook
如果你主要是为了“入门可用”,建议先把 5.2 跑通,再决定怎么持久化。
多 IP 很多人最后是为了邮件。
但自建邮件服务最卡人的,往往不是 Postfix,而是:
- 25 端口
- IP 信誉
- PTR/反向解析
如果你就是冲着邮件去的,强烈建议你把这篇当“踩坑清单”过一遍:
