При настраивании разного рода сервисов приходится сталкиваться с тем, что на одном интерфейсе, находится несколько алиасов. Всё бы ничего, но возникают вопросы: с каким src address будет уходить пакет?
Если алиасы из разных подсетей, то ответ сразу ясен. А если нет?
Linux
По дефолту берётся “первичный” адрес интерфейса, то есть тот, который не алиас. В нашем примере берётся адрес 10.5.6.114:
eth0 Link encap:Ethernet HWaddr 08:00:27:e5:73:35 inet addr:10.5.6.114 Bcast:10.5.7.255 Mask:255.255.252.0 inet6 addr: fe80::a00:27ff:fee5:7335/64 Scope:Link eth0:1 Link encap:Ethernet HWaddr 08:00:27:e5:73:35 inet addr:10.5.5.78 Bcast:10.5.7.255 Mask:255.255.252.0
Но это поведение можно изменить:
# ip route add <HOST|NET> dev <ALIAS_DEV> src <ALIAS_SRC_IP>
Пример:
# ip route add 10.5.5.6/32 dev eth0:1 src 10.5.5.78
Посмотрим, с каким src address будут уходить наши пакеты, в зависимости от dst address:
# ip route get 10.5.5.6
10.5.5.6 dev eth0 src 10.5.5.78
cache
# ip route get 10.5.5.55
10.5.5.55 dev eth0 src 10.5.6.114
cache ipid 0xd02c
# ip route get 10.5.5.56
10.5.5.56 dev eth0 src 10.5.6.114
cache
Solaris
– Новый метод.
Здесь существует параметр usesrc в команде ipadm:
# ipadm show-ifprop -p usesrc -m ipv4 vrrp99 IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE vrrp99 usesrc ipv4 rw none -- none -- # ipadm set-ifprop -p usesrc=net0 -m ipv4 vrrp99 # ipadm show-ifprop -m ipv4 -p usesrc vrrp99 IFNAME PROPERTY PROTO PERM CURRENT PERSISTENT DEFAULT POSSIBLE vrrp99 usesrc ipv4 rw net0 net0 none --
– Старый метод.
Здесь существует параметр -setsrc в команде route:
# ipadm show-addr | grep 10.5.5. net0/v4 static ok 10.5.5.219/22 net0/new static ok 10.5.5.31/22 # route add -host 10.5.5.6 10.5.5.88 -setsrc 10.5.5.31 # route get 10.5.5.6 route to: 10.5.5.6 destination: 10.5.5.6 mask: 255.255.255.255 gateway: 10.5.5.88 setsrc: 10.5.5.31 interface: net0 flags: <UP,GATEWAY,HOST,DONE,STATIC,SETSRC> recvpipe sendpipe ssthresh rtt,ms rttvar,ms hopcount mtu expire 0 0 0 0 0 0 1500 0
При этом, вместо 10.5.5.88 может стоять любой доступный хост (но он должен быть обязательно), но не сам 10.5.5.31. Иначе команда будет ругаться
# route add -host 10.5.5.6 10.5.5.31 -setsrc 10.5.5.31
add host 10.5.5.6: gateway 10.5.5.31: Network is unreachable
FreeBSD
В старых версиях тоже был параметр -setsrc к команде route, но потом его убрали. Единственное решение – это использовать setfib. То есть обязательная пересборка ядра. О том, как это сделать, написано здесь. При этом, это справедливо для любого созданного интерфейса, а не только carp (то есть по сути, вы можете создать tun, gif, … интерфейс и проделать с ним всё то, что описано в статье). Зато для IPv6 можно заюзать недокументированный параметр deprecated (пример не мой, взят из сети):
# ifconfig gif0 inet6 2001:470:1f08:84f::2 2001:470:1f08:84f::1 prefixlen 128 deprecated # ifconfig gif0 gif0: flags=8151<UP,POINTOPOINT,RUNNING,PROMISC,MULTICAST> metric 0 mtu 1280 tunnel inet 31.193.132.199 --> 216.66.80.26 inet6 fe80::be30:5bff:feda:b396%gif0 prefixlen 64 scopeid 0x7 inet6 2001:470:1f09:84f::1 prefixlen 64 inet6 2001:470:1f09:84f::2 prefixlen 64 inet6 2001:470:1f09:84f:: prefixlen 64 inet6 2001:470:1f09:84f::3 prefixlen 64 inet6 2001:470:1f09:84f::5e4c:dad4 prefixlen 64 inet6 2001:470:1f09:84f::5e4c:dad5 prefixlen 64 inet6 2001:470:1f09:84f::1fc1:84c7 prefixlen 64 inet6 2001:470:1f08:84f::2 --> 2001:470:1f08:84f::1 prefixlen 128 deprecated nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> options=1<ACCEPT_REV_ETHIP_VER> # ping6 home.b0rken.org PING6(56=40+8+8 bytes) 2001:470:1f09:84f::1 --> 2001:470:1f08:84e::2
OpenBSD
Для Openbsd решения мне не удалось найти.