多出口IP指定

本文介绍在Linux系统中,当主机绑定多个IP地址时,如何指定特定IP作为源地址的方法。包括通过修改路由表的src参数和使用iptables进行源地址转换。

多IP指定出口IP地址 如何指定云服务器源IP?

如果一个主机绑定有多个IP地址,那么在被动响应和主动发起连接两种方式中,源IP地址的选择机制肯定是有所差异的。主机在接收外部数据包,并发送响应数据包时,响应源地址显然就是客户端请求的地址,这是非常容易理解的,如客户端向主机的1.1.2.3:80发起请求,那么主机响应数据包的源IP地址一定是1.1.2.3

那么当主机对外主动发起请求时,数据包的源IP地址如何选择?这个问题我们可能一般很少深入了解, 为了弄清楚这个问题,我发了不少时间,广泛查阅各种资料,目前得出的结论如下:

 

Linux 2.2 选择源IP的三种机制

§ 1. 应用程序可以通过bind(2)系统调用,应用至sendmsg(2)调用上,并通过辅助数据对象IP_PKTINFO,从而显式指定源IP地址。在这种情况下,操作系统内核仅仅检查其源IP地址是否正确,否则产生相应的错误。

§ 2. 如果应用程序没有指定源IP地址,包含源IP的路由表将决定数据包源IP地址,通过设置ip route命令的src参数,从而指定源IP地址。如果路由表没有包含src属性,则使用主要IP地址。

§ 3. 其它情况下内核搜寻绑定定数据包路由接口上的IP地址,IPv6选择第一个可用的IP地址。IPv4情况下,尽量选择与目标IP处于同一子网的源IP,如果目标IP与自己的所有ip没有处于同一子网,则使用第二种算法。

相同/不同子网情况

默认情况下,如果Linux的网卡有多个IP且位于不同的子网之中,如果数据包目标地址为某个子网中的IP, 那么对应的与目标同子网的IP将会被使用。如果eth0有两个IP 192.168.1.12/24,  10.1.1.1/8,那么到10.0.0.0子网的数据包的源地址将使用10.1.1.1 当然可以使用ip routesrc属性指定源址。

如果绑定的几个IP处于同一个子网内,那么主要IP地址将被使用(如eth0接口上的IP也可以使用iptables修改数据包的源地址实现之,如:

iptables -t nat -I POSTROUTING -o eth0 -d 1.2.3.4/0 -s 192.168.100.1 -j SNAT --to-source 192.168.100.2

 IP指定出口ip实例

原理分析及处理办法我们已经分析完毕,接下来使用实际的例子展示

目标:当此主机对外发起新连接时,源IP地址使用192.168.0.22, 不使用默认的192.168.0.250

环境:Linux 主机绑定有以下几个IP(网关为192.168.0.1
eth0 192.168.0.250/24,  eth0: 1  192.168.0.22/24,   eth0:2 192.168.0.23/24

另外,绑定多个IP可使用ip addr add命令,不产生子接口。

在上述案例中192.168.0.250将成为默认主要IP

 

方法一:修改路由表的源IP属性
查看系统的 ip 地址及路由表详细信息 ( 加粗字体是输入的内容 )

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

[root@localhost ~]# ip addr

 

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue

 

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

 

inet 127.0.0.1/8 scope host lo

 

inet 192.168.100.250/32 scope global lo

 

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000

 

link/ether f4:6d:04:76:ca:98 brd ff:ff:ff:ff:ff:ff

 

inet 192.168.0.250/24 brd 192.168.0.255 scope global eth0

 

inet 172.16.25.1/24 scope global eth0

 

inet 192.168.0.22/24 scope global secondary eth0

 

inet 192.168.0.23/24 scope global secondary eth0

 

请注意 192.168.0.250是global状态,而其它地址是secondary状态。

 

1

2

3

4

5

6

7

8

9

[root@localhost ~]# ip route

 

192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.250

 

172.16.25.0/24 dev eth0  proto kernel  scope link  src 172.16.25.1

 

169.254.0.0/16 dev eth0  scope link

 

default via 192.168.0.1 dev eth0

注意以上输出,会发现到同一子网的路由的源IP地址会使用主要IP地址。而到默认网关的路由没有指定源IP(实际上会用与网关同一子网的主要IP)。
修改路由表,让系统使用指定IP(192.168.0.22)作为源址:

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@localhost ~]# ip route change default dev eth0 src 192.168.0.22

 

[root@localhost ~]# ip route change to 192.168.0.0/24 dev eth0 src 192.168.0.22

 

[root@localhost ~]# ip route

 

192.168.0.0/24 dev eth0  scope link  src 192.168.0.22

 

172.16.25.0/24 dev eth0  proto kernel  scope link  src 172.16.25.1

 

169.254.0.0/16 dev eth0  scope link

 

default dev eth0  scope link  src 192.168.0.22

方法二,使用iptables修改源IP地址:

1

iptables -t nat -I POSTROUTING -o eth0 -d 0.0.0.0/0 -s 192.168.0.250 -j SNAT --to-source 192.168.0.22

方法二比较简单,大家可以写好脚本来切换出口IP地址

参考文章

http://linux-ip.net/gl/ip-cref/node155.html
http://serverfault.com/questions/12285/when-ip-aliasing-how-does-the-os-determine-which-ip-address-will-be-used-as-sour

多出口 IP 导致 FTP 传输失败,可以尝试以下解决办法: ### 动态 DNS 服务 使用动态 DNS(DDNS)服务,将域名与多个动态变化的出口 IP 绑定。当出口 IP 发生变动时,DDNS 服务会自动更新域名对应的 IP 地址。在 FTP 客户端配置中,使用该域名而不是具体的 IP 地址进行连接。这样,即使出口 IP 改变,由于域名解析的是最新的 IP,FTP 推送仍能正常进行。 ### 定期检查和更新 IP 配置 编写脚本定期检查出口 IP 的变化情况。当检测到 IP 变动时,自动更新 FTP 客户端或服务器端的 IP 配置信息。在 Windows 环境下,可结合任务计划程序,设置脚本每天在特定时间运行,以确保配置信息的及时性。以下是一个 Python 示例代码,用于检查 IP 变化并更新配置: ```python import requests import configparser # 获取当前出口 IP def get_current_ip(): try: response = requests.get('https://api.ipify.org') return response.text except requests.RequestException: return None # 读取配置文件中的 IP def read_config_ip(config_file): config = configparser.ConfigParser() config.read(config_file) if 'FTP' in config and 'ip' in config['FTP']: return config['FTP']['ip'] return None # 更新配置文件中的 IP def update_config_ip(config_file, new_ip): config = configparser.ConfigParser() config.read(config_file) if 'FTP' not in config: config['FTP'] = {} config['FTP']['ip'] = new_ip with open(config_file, 'w') as configfile: config.write(configfile) # 主函数 def main(): config_file = 'ftp_config.ini' current_ip = get_current_ip() if current_ip: config_ip = read_config_ip(config_file) if current_ip != config_ip: update_config_ip(config_file, current_ip) print(f"IP 已更新为: {current_ip}") else: print("IP 未发生变化") else: print("无法获取当前 IP") if __name__ == "__main__": main() ``` ### 联系网络服务提供商 与网络服务提供商沟通,了解是否可以申请静态 IP 地址或相对稳定的 IP 分配策略。静态 IP 地址不会随时间或网络状态变化而改变,使用静态 IP 可以从根本上解决因出口 IP 变动导致的 FTP 推送失败问题。不过,申请静态 IP 可能需要额外的费用。 ### 监控和报警机制 建立监控和报警机制,实时监测 FTP 推送的状态。当检测到 FTP 推送失败时,及时通知管理员。可以通过邮件、短信等方式进行报警,管理员收到通知后,能够迅速手动更新 IP 配置或采取其他措施。 ### 配置高可用性 FTP 服务器 搭建高可用性的 FTP 服务器架构,使用多个 IP 地址或多个服务器节点。当一个 IP 地址出现问题时,系统可以自动切换到其他可用的 IP 地址或服务器节点,确保 FTP 推送服务的连续性。 ### 调整 FTP 服务器配置 在 FTP 服务器配置中,确保服务器返回给客户端的是正确的公网 IP 地址。例如,在 vsftpd 服务器中,可以通过设置 `pasv_address` 参数来指定返回给客户端的 IP 地址,避免返回内网 IP 导致客户端无法连接。示例配置如下: ```plaintext # vi /etc/vsftpd/vsftpd.conf pasv_address=111.13.101.208 # 这里返回映射的公网 IP 给客户端 # service vsftpd restart ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值