여러 네트워크 인터페이스가 있고 각각 하나 이상의 IP 주소가 있는 컴퓨터가 있습니다. 이러한 IP 주소는 동일한 서브넷에 있을 수도 있고 그렇지 않을 수도 있습니다. 예를 들어 결과는 ip a
다음과 같습니다.
1: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 11:11:11:11:11:11 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.2/24 brd 10.0.1.255 scope global eno1
valid_lft forever preferred_lft forever
inet 10.12.1.3/24 brd 10.12.1.255 scope global secondary eno1:0
valid_lft forever preferred_lft forever
2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 22:22:22:22:22:22 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.4/24 brd 10.0.1.255 scope global eno2
valid_lft forever preferred_lft forever
inet 192.168.1.3/24 brd 192.168.1.255 scope global secondary eno2:0
valid_lft forever preferred_lft forever
2: eno3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 33:33:33:33:33:33 brd ff:ff:ff:ff:ff:ff
inet 172.23.1.2/24 brd 172.23.1.255 scope global eno3
valid_lft forever preferred_lft forever
내가 원하는 것은 인터페이스로 들어오는 트래픽에 대한 응답이 동일한 인터페이스를 통해 나가고 대상에 관계없이 특정 인터페이스를 통해 트래픽을 보내도록 애플리케이션에 지시할 수 있다는 것입니다.
예를 들어, 네트워크의 다른 시스템 ping 10.0.1.2
에서 온 경우 응답은 eno2를 통해 라우팅되므로 모든 종류의 문제가 발생합니다.192.168.1.0/24
어떻게 해야 하나요? 라우팅 테이블을 여러 개 설정할 수 있나요? 인터페이스 이름이나 다른 이름으로 수신 패킷에 태그를 지정할 수 있습니까?
답변1
참고: 설정에 필요한 사항지적 재산권네트워크 10.0.1.0/24 및 192.168.1.0/24가 동일한 네트워크에 있습니다.이더넷회로망. 그렇지 않은 경우에는 다음 사항을 제공해야 합니다.상세한네트워크 토폴로지에서는 호스트를 하나만 제공하는 것만으로는 충분하지 않습니다. 여기서 문제가 이미 재현되고 수정될 수 있지만 이에 맞게 이 답변을 편집하겠습니다. 이것이 바로 최종 모델 설정에서 두 개의 브리지를 연결한 이유입니다.1번그리고이노 2동일한 LAN 내에서. 또한 IP 10.0.1.1/24 / 192.168.1.1/24로 라우터를 추가했습니다.
두 가지 설정을 여러 번 언급할 것입니다.rp_filter
그리고arp_filter
, 혼동하지 마십시오.
동일한 솔루션의 두 가지 다른 문제:
- ARP 플럭스(참고: 링크의 솔루션에 제공된 두 매개변수는 의 사용으로 대체되었습니다.
arp_filter
) 이는 Linux가 기본적으로 ARP의 라우팅 규칙을 실제로 따르지 않기 때문에 존재합니다. 두 인터페이스의 주소가 동일한 IP LAN에 있으면 문제가 발생할 수 있습니다. 이 문제는 해결되어야 합니다. 그렇지 않으면 몇 분 동안 지속되는 이상한 문제가 발생할 수 있습니다. 따라서arp_filter
경로를 일치시키려면 활성화되어야 합니다. 다음 문제를 해결하는 정책 라우팅이 이 문제도 해결하므로 여기서는 추가 노력 없이 작동합니다. - 라우팅 문제, 기본적으로 다음 방법을 통해 192.168.0/24에 대한 경로를 직접 볼 수 있기 때문입니다.이노 2, 그래서1번답변은 절대 고려되지 않습니다. 일단 설정되면
rp_filter
eno1을 통해 들어오는 트래픽이 삭제되거나 응답이 없을 수도 있습니다. 설정되지 않았거나 느슨한 경우 10.0.1.2에 쿼리하십시오.1번잘못된 인터페이스를 통해 응답 받기:이노 2.
결론적으로:
ARP 수정나가는동작으로 인해 예외가 수정됩니다.들어오는IP 문제. 10.0.1.2로 들어오는 요청은 어디에서 오는가?이노 2. 이는 낮추어 보면 알 수 있다1번아래 모델 설정에서는 1~2분 후에(라우터의 ARP 캐시가 만료됨) 10.0.1.2에 대한 ping 요청이 수신되고 모든 답변을 사용할 수 있습니다.이노 2. 지금 다시 가져와1번up은 들어오는 IP를 복원하지 않습니다. 이는 라우터의 ARP 캐시에 여전히 10.0.1.2가 있기 때문입니다.이노 2MAC 주소는 대신 해당 주소에 대해 먼저 유니캐스트 쿼리를 수행하여 새로 고쳐집니다.1번MAC 주소. 일시적으로 감소이노 2라우터에서 ARP를 플러시합니다(또는 DAD/갭이용신청
arping
호스트에서) 이전 상황으로 되돌아갑니다(응답이 없는 경우rp_filter=1
).내 강조, 에서리눅스/문서/네트워크/ip-sysctl.txt의
arp_filter
:arp_filter - BOOLEAN
1 - 동일한 서브넷에 여러 네트워크 인터페이스가 있고
각 인터페이스에 대해 ARP에 응답할 수 있습니다.
커널이
ARP를 기반으로 IP에서 패킷을 라우팅 할지 여부이 인터페이스 외부(
따라서 작동하려면 소스 기반 라우팅을 사용해야 합니다.). 즉,
arp 요청에 응답할 카드(보통 1개)를 제어할 수 있습니다.0 - (기본값)
커널은 다른 인터페이스의 주소를 사용하여 arp 요청에 응답할 수 있습니다.. 이것은 잘못된 것처럼 보일 수도 있지만,
성공적인 의사소통 가능성을 높이기 때문에 종종 의미가 있습니다.
Linux의 IP 주소는 전체 호스트가 소유합니다.
, 특정 인터페이스를 통하지 않고 .
이 동작은 로드 밸런싱과 같은 보다 복잡한 설정에서만 문제를 발생시킵니다.conf/{all,interface}/arp_filter 중 하나 이상이
TRUE로 설정되면 인터페이스의 arp_filter가 활성화되고,
그렇지 않으면 비활성화됩니다.수리하다나가는IP 라우팅 문제를 해결하려면 IP당 하나씩 추가 라우팅 테이블이 필요합니다. 문제의 각 IP에는 포함되지 않는 특정 경로 테이블을 사용하도록 해당 IP를 선택하는 특정 규칙이 있어야 합니다. 따라서 다른 로컬 IP의 관련 경로를 무시하고 대신 지정된 인터페이스를 강제합니다.
이러한 설정을 배포할 계획이라면 일부 자동화를 수행해야 할 것입니다. 이러한 종류의 문제를 해결하려면 일반적으로 IP당 하나의 라우팅 테이블이 필요하고 최신 커널에는 2^32개의 라우팅 테이블이 있을 수 있으므로 전체 IPv4를 라우팅 테이블에 매핑할 수도 있습니다(몇 가지 특수 테이블의 수를 고려). 충분히 낮음) IP 0.xxx/8이 예약되어 있으므로 매핑 및 덮어쓰기를 방지합니다. 이 문제를 완화하기 위해 몇 가지 쉘 기능을 추가했습니다. 이러한 라우팅 테이블 번호에는 이름이 필요하지 않지만 선택적으로 /etc/iproute2/rt_tables
동일한 방식으로 이름을 지정할 수 있으며 동일한 목적으로 IP 주소의 이름을 /etc/hosts
. 여기서는 필요하지 않습니다.
이제 설명이 되었기를 바랍니다. 이를 수정하는 방법은 다음과 같습니다.
호스트 시스템에서 다음 스크립트를 실행합니다.
fix.sh
:
#!/bin/sh
map_localip_to_interface () {
ip -brief address show to "$1" | awk '{ print $1 }'| sed 's/@.*$//'
}
map_ip_to_table () {
printf '%s\n' "$1" | awk -F. '{ print (((($1*256)+$2)*256)+$3)*256+$4 }'
}
#not used here
map_table_to_ip () {
local ip
local n="$1"
for i in 1 2 3 4; do
ip="$(($n%256)).$ip"
n=$(($n/256))
done
printf '%s\n' "$ip" | sed 's/\.$//'
}
ip rule add from 10.0.1.2 table $(map_ip_to_table 10.0.1.2)
ip rule add from 10.0.1.4 table $(map_ip_to_table 10.0.1.4)
ip rule add from 192.168.1.3 table $(map_ip_to_table 192.168.1.3)
ip route add table $(map_ip_to_table 10.0.1.2) 10.0.1.0/24 dev $(map_localip_to_interface 10.0.1.2)
ip route add table $(map_ip_to_table 10.0.1.2) default via 10.0.1.1 dev $(map_localip_to_interface 10.0.1.2)
ip route add table $(map_ip_to_table 10.0.1.4) 10.0.1.0/24 dev $(map_localip_to_interface 10.0.1.4)
ip route add table $(map_ip_to_table 10.0.1.4) default via 10.0.1.1 dev $(map_localip_to_interface 10.0.1.4)
ip route add table $(map_ip_to_table 192.168.1.3) 192.168.1.0/24 dev $(map_localip_to_interface 192.168.1.3)
ip route add table $(map_ip_to_table 192.168.1.3) default via 192.168.1.1 dev $(map_localip_to_interface 192.168.1.3)
sysctl -q -w net.ipv4.conf.eno1.arp_filter=1
sysctl -q -w net.ipv4.conf.eno2.arp_filter=1
결과는 다음과 같습니다.
# ip rule
0: from all lookup local
32763: from 192.168.1.3 lookup 3232235779
32764: from 10.0.1.4 lookup 167772420
32765: from 10.0.1.2 lookup 167772418
32766: from all lookup main
32767: from all lookup default
# ip route show table all |grep 'table [1-9]'
default via 10.0.1.1 dev eno1 table 167772418
10.0.1.0/24 dev eno1 table 167772418 scope link
default via 192.168.1.1 dev eno2 table 3232235779
192.168.1.0/24 dev eno2 table 3232235779 scope link
default via 10.0.1.1 dev eno2 table 167772420
10.0.1.0/24 dev eno2 table 167772420 scope link
# sysctl net.ipv4.conf.eno{1,2}.arp_filter
net.ipv4.conf.eno1.arp_filter = 1
net.ipv4.conf.eno2.arp_filter = 1
이는 문제의 모든 IP에 대해 이를 사용할 때 라우팅 스택이 개인 라우팅 테이블로 전환되어 올바른 네트워크 인터페이스가 사용된다는 것을 의미합니다. ARP는 동일한 원칙을 따릅니다.
동일한 설정을 사용하면 로컬에서 시작된 나가는 IP가 제대로 작동할 수 있습니다. 192.168.1.100이 웹 서버인 경우:
ping -I 10.0.1.2 192.168.1.100 # through eno1 and via router
ping -I 10.0.1.4 192.168.1.100 # through eno2 and via router
ping -I 192.168.1.3 192.168.1.100 # through eno2 directly
마찬가지로 192.168.1.100에서 socat(1.7.3.2)를 사용하는 경우 다음 명령을 실행합니다.
socat tcp4-listen:5555,reuseaddr,fork exec:'printenv SOCAT_PEERADDR'
그런 다음 멀티홈 호스트에서 모든 것이 잘 되었다는 응답을 받을 수 있습니다.
# socat tcp4:192.168.1.100:5555 -
192.168.1.3
# socat tcp4:192.168.1.100:5555,bind=10.0.1.2 -
10.0.1.2
# socat tcp4:192.168.1.100:5555,bind=10.0.1.4 -
10.0.1.4
tcpdump
트래픽이 예상 인터페이스를 통과하고 있는지 확인할 수 있습니다 .
다른 IP에 더 많은 라우팅 문제가 있는 경우 이제 무엇을 해야 할지 알아야 합니다.
노트:
- 여기서 10.12.1.3을 놔뒀는데 이미 켜져있으니까1번이제 이를 가지게 되었으므로
arp_filter=1
제대로 작동하려면 자체 라우팅 테이블과 규칙도 받아야 합니다. - 호스트도 라우팅하는 경우 규칙과 라우팅 테이블을 개선해야 할 수 있습니다. 테스트해야합니다.
모형 설정:
다음 스크립트를 루트로 실행하세요 setup.sh
. 이제 문제는 다음과 같이 재현될 수 있습니다.
1학기:
ip netns exec mhost tcpdump -l -e -n -s0 -p -i eno1
2학기:
ip netns exec mhost tcpdump -l -e -n -s0 -p -i eno2
항목 3:
ip netns exec h1921681100 ping -n 10.0.1.2
응답이 없습니다. 최소한 이렇게 하세요:
ip netns exec mhost sysctl -w net.ipv4.conf.eno1.rp_filter=2
비대칭 라우팅이 허용됩니다.1번그리고 떠나다이노 2(또는 모두 통과이노 2"ARP 플럭스" 효과가 유효한 경우).
위 스크립트를 실행하면 fix.sh
모든 문제가 해결됩니다.
ip netns exec mhost sh fix.sh
setup.sh
:
#!/bin/sh
if ip netns id | grep -qv '^ *$' ; then
printf 'ERROR: leave netns "%s" first\n' $(ip netns id) >&2
exit 1
fi
hosts='mhost router h1921681100'
nets='net1001 net1921681 net10121 net172231'
for ns in $hosts $nets; do
ip netns del $ns 2>/dev/null || :
ip netns add $ns
ip netns exec $ns sysctl -q -w net.ipv6.conf.default.disable_ipv6=1
ip netns exec $ns sysctl -q -w net.ipv4.conf.default.rp_filter=1
ip netns exec $ns sysctl -q -w net.ipv4.conf.all.rp_filter=1
done
for ns in $hosts; do
ip -n $ns link set lo up
done
bmac=1
for ns in $nets; do
ip -n $ns link add bridge0 address 02:00:00:00:00:$(printf '%02d' $bmac) type bridge
ip -n $ns link set bridge0 up
bmac=$(($bmac+1))
done
link_lan () {
[ "$1" = "$2" ] && return 1
ip -n $2 link add p-$1 type veth peer netns $1 name p-$2 2>/dev/null || return 1
ip -n $2 link set p-$1 master bridge0 up
ip -n $1 link set p-$2 master bridge0 up
}
link_lan net1001 net1921681
ip -n h1921681100 link add eth0 type veth peer netns net1921681 name p-h1921681100
ip -n h1921681100 link set eth0 up
ip -n net1921681 link set p-h1921681100 master bridge0 up
ip -n h1921681100 address add 192.168.1.100/24 broadcast 192.168.1.255 dev eth0
ip -n h1921681100 route add default via 192.168.1.1
ip netns exec router sysctl -q -w net.ipv4.conf.default.forwarding=1
ip -n router link add eth10011 type veth peer netns net1001 name p-router10011
ip -n router link set eth10011 up
ip -n net1001 link set p-router10011 master bridge0 up
ip -n router address add 10.0.1.1/24 broadcast 10.0.1.255 dev eth10011
ip -n router link add eth1921681 type veth peer netns net1921681 name p-router1921681
ip -n router link set eth1921681 up
ip -n net1921681 link set p-router1921681 master bridge0 up
ip -n router address add 192.168.1.1/24 broadcast 192.168.1.255 dev eth1921681
ip netns exec mhost sysctl -q -w net.ipv4.conf.default.forwarding=0
ip -n mhost link add eno1 type veth peer netns net1001 name p-mhosteno1
ip -n mhost link set eno1 up
ip -n net1001 link set p-mhosteno1 master bridge0 up
ip -n mhost address add 10.0.1.2/24 broadcast 10.0.1.255 dev eno1
ip -n mhost address add 10.12.1.3/24 broadcast 10.12.1.255 dev eno1
ip -n mhost link add eno2 type veth peer netns net1921681 name p-mhosteno2
ip -n mhost link set eno2 up
ip -n net1921681 link set p-mhosteno2 master bridge0 up
ip -n mhost address add 10.0.1.4/24 broadcast 10.0.1.255 dev eno2
ip -n mhost address add 192.168.1.3/24 broadcast 192.168.1.255 dev eno2
ip -n mhost link add eno3 type veth peer netns net172231 name p-mhosteno3
ip -n mhost link set eno3 up
ip -n net172231 link set p-mhosteno3 master bridge0 up
ip -n mhost address add 172.23.1.2/24 broadcast 172.23.1.255 dev eno3