두 개의 서로 다른 서브넷 에 연결된 두 개의 인터페이스가 있는 서버가 있습니다 dhcp
. 이 2개의 서로 다른 서브넷은 2개의 서로 다른 인터페이스를 통해 동일한 스위치에 연결됩니다.
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
23: enp10s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c4:00:ad:a4:e3:38 brd ff:ff:ff:ff:ff:ff
inet 192.168.201.232/24 brd 192.168.201.255 scope global enp10s0
valid_lft forever preferred_lft forever
25: enp11s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c4:00:ad:a4:e3:39 brd ff:ff:ff:ff:ff:ff
inet 192.168.203.3/24 brd 192.168.203.255 scope global enp11s0
valid_lft forever preferred_lft forever
inet6 fe80::c600:adff:fea4:e339/64 scope link
valid_lft forever preferred_lft forever
노선:
# ip r
default via 192.168.201.1 dev enp10s0
192.168.201.0/24 dev enp10s0 proto kernel scope link src 192.168.201.232
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3
먼저 노트북에서 ping을 실행하여 해당 장치의 tcpdump를 통해 요청과 응답을 192.168.201.232
볼 수 있습니다.icmp
# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:42:05.240967 IP (tos 0x0, ttl 62, id 53809, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.201.232: ICMP echo request, id 55768, seq 1, length 64
11:42:05.240994 IP (tos 0x0, ttl 64, id 42288, offset 0, flags [none], proto ICMP (1), length 84)
192.168.201.232 > 192.168.1.30: ICMP echo reply, id 55768, seq 1, length 64
ping을 실행해도 192.168.203.3
응답이 없습니다. tcpdump 출력은 다음과 같습니다.
# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:43:57.037535 IP (tos 0x0, ttl 62, id 19363, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 1, length 64
11:43:58.060756 IP (tos 0x0, ttl 62, id 19364, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 2, length 64
이 패킷은 어떻게 되나요?
왜 icmp
응답이 없나요? 내 IP가 다음과 같으므로 응답이 기본 gw()로 이동하기를
원합니다 .icmp
192.168.201.1
192.168.1.30
아무것도 없고 iptables
, 스텟도 오르지 않습니다 netstat -s
.
DHCP를 제거했는데 인터페이스에 enp10s0
IP가 부여되지 않아 경로가 하나만 남게 됩니다.
# ip r
default via 192.168.203.1 dev enp11s0
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3
내 노트북에서 핑을 보내면 192.168.203.3
작동합니다.
답변1
항상 추가적인 라우팅 복잡성이 발생하는 멀티홈 서버가 있습니다.
네트워크는 다소 복잡할 수 있지만 다음과 같이 보일 수 있습니다.
┏━━━━━━┓
┃laptop┃
┗━━━━━━┛
192.168.1.30/24
┊
lan1
┊
192.168.1.1/24
┌─────────┐
│ clients │
│ router │
└─────────┘
x.x.x.x
┊
y.y.y.y
┌─────────┐
192.168.201.1/24 servers 192.168.203.1/24
╭┄┄┄┄┄┄┄┄┄┄┄┄┄│ router │┄┄┄┄┄┄┄┄┄┄┄┄┄╮
┆ └─────────┘ ┆
┆ ┆
lan201 lan203
┆ ┆
┆ ┏━━━━━━━━━┓ ┆
╰┄┄┄┄┄┄┄┄┄┄┄┄┄┃ ┃┄┄┄┄┄┄┄┄┄┄┄┄┄╯
192.168.201.232/24 server 192.168.203.3/24
┃ ┃
┗━━━━━━━━━┛
패킷이 무시되는 이유는 무엇입니까?
문제는 "스푸핑 방지 보호"라는 기능이 활성화된 서버로 인해 발생했을 가능성이 높습니다.엄격한 역방향 경로 전달(SRPF). 즉, 들어오는 패킷은 응답이 동일한 인터페이스를 사용하여 다시 라우팅되는 경우에만 인터페이스를 통과할 수 있습니다.
두 인터페이스가 모두 구성되어 있고 기본 경로가 192.168.201.1을 사용하고 노트북에서 192.168.201.232를 핑하면 패킷은 "왼쪽 경로"를 통해 서버로 이동하고 "왼쪽 경로"를 통해 서버에서 반환됩니다. 서버는 커널에 라우팅 결정이 무엇인지 물어볼 수 있습니다.
노트북 가는 방법:
# ip route get from 192.168.201.232 192.168.1.30
192.168.1.30 from 192.168.201.232 via 192.168.201.1 dev enp10s0 uid 0
cache
사용enpu10s0.
우리는 들어오는 패킷이 동일한 인터페이스(enpu10s0) 이것이 서버의 라우터가 수행할 작업임을 알고 있기 때문입니다.
# ip route get from 192.168.1.30 iif enp10s0 192.168.201.232
local 192.168.201.232 from 192.168.1.30 dev lo table local
cache <local> iif enp10s0
나가는 패킷과 같은 쪽에 있으므로 들어오는 패킷이 허용되고 로컬 시스템으로 라우팅됩니다.
이제 192.168.203.3을 ping하면 패킷이 라우팅되어 "올바른 경로"로 이동하고 서버의 라우팅 구성은 서버를 "왼쪽 경로"에 두는 것으로 표시됩니다. 이는 비대칭 경로이며 이전 SRPF 검사에 실패했습니다. 다른 인터페이스입니다.
이 상황에 대한 결정을 커널에 다시 요청할 수 있습니다. 응답(있는 경우)은 다음과 같이 라우팅됩니다.
# ip route get from 192.168.203.3 192.168.1.30
192.168.1.30 from 192.168.203.3 via 192.168.201.1 dev enp10s0 uid 0
cache
기본 경로를 사용하므로enpu10s0, 수신 데이터 패킷:
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3
RTNETLINK answers: Invalid cross-device link
들어오는 인터페이스 때문에 SRPF에 의해 거부되었습니다.enpu11s0나가는 인터페이스와 일치하지 않습니다.enpu10s0이 IP 주소에 응답하는 데 사용됩니다.
"왼쪽 경로"를 비활성화하여 기본 경로를 변경하고 "오른쪽 경로"에서 DHCP의 기본 경로를 상속하면 모든 것이 다음으로 변경됩니다.enpu11s0다시 작동합니다.
어떻게 작동하게 만들까요?
별로 도움이 안 될 수도 있는 것
시스템에 알릴 수 있습니다.장애를 입히다확인하거나안심하다도착한다느슨한 역방향 경로 전달. 존재하는 기본 경로의 경우 두 효과는 비슷하지만(즉, 전혀 효과가 크지 않음) Linux에서 이를 완화(설정 2)하는 것이 활성화할 때 비활성화(0 설정)하는 것보다 더 짜증납니다. 이것 때문에 다른 곳에서는 쉽게이 구성에서 가장 큰 값이 승리합니다.. 시스템 시작 시 활성화될 수 있습니다.
/etc/sysctl.d
(YMMV) 거기에서 편집할 수 있습니다. 그래서:sysctl -w net.ipv4.conf.enp11s0.rp_filter=2
이전 쿼리는 더 이상 실패하지 않습니다.
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3 local 192.168.203.3 from 192.168.1.30 dev lo table local cache <local> iif enp11s0
이제 두 개의 tcpdump가 있습니다. 각 서버 인터페이스에 하나씩 들어오는 패킷을 볼 수 있어야 합니다.enpu11s0및 발신 응답enpu10s0.
노트북이 응답을 받으면 작업이 완료된 것이며 하루 만에 통화할 수 있습니다.
아마도 그렇지 않을 것입니다. 왜냐하면 경로를 따라 다음 네트워크 요소인 서버의 라우터가반품SRPF를 구현합니다. 또는 방화벽으로도 사용할 수 있으며 192.168.201.0/24의 패킷만 허용하는 인터페이스에서 오는 패킷 192.168.203.3을 의심스러운 것으로 간주할 수 있습니다(SRPF의 목표이기도 한 스푸핑 방지 보호). 따라서 패킷은 한 단계 후에 삭제될 가능성이 높습니다.
작동 방식: 정책 라우팅
멀티 호밍이 포함될 때마다,정책 기반 라우팅사용해야 합니다. 이를 통해 결정 선택자로 대상 주소뿐만 아니라 다양한 기타 기준(가장 일반적으로 소스 주소)을 사용하여 라우팅을 선택할 수 있습니다. 여기에는 소스 주소도 필요합니다. Linux에서는 추가 라우팅 테이블(일반적으로 대상을 선택기로 사용)을 사용하고 규칙을 사용하여 적절한 라우팅 테이블을 선택(여기에서는 소스를 선택기로 사용)하여 이를 수행합니다. 설정은 소스 주소에 따라 달라지므로 DHCP와 같은 동적 환경에 통합하기가 어렵습니다. 확실히 가능하지만 데몬은 다음과 같습니다.dh클라이언트또는네트워크 관리자각각에는 스크립트에 삽입할 고유한 후크 세트가 있으며 고정 IP 주소 구성을 사용하고 이러한 주소를 DHCP 서버에 예약되어 선언하면 시간을 절약할 수 있습니다.
기본 테이블의 경로는 추가 테이블에 부분적으로 복사되어야 합니다. 서버가 라우터이기도 한 경우(예: LXC, Docker, VM 실행...) 더 많은 경로를 고려해야 하며 다른 라우팅 테이블에 복사할 수도 있습니다. 물론 이러한 경로가 동적(컨테이너가 실행되는 동안 표시됨)인 경우 구성이 더 복잡해집니다. 늘 그렇듯이
ip route get
여기에는 많은 도움이 있습니다.따라서 각 끝에 대한 라우팅 테이블을 만들고(이 테이블에는 덜 임의적인 값 201과 203을 사용하겠습니다) 이 끝에 관련하여 필요한 것만 복사합니다. 추가각기본 경로 중 하나입니다. 여전히 기본 경로는 하나만 사용할 수 있지만 경로 테이블당 하나만 사용할 수 있습니다. 여기에 기본 경로를 추가하는 것만으로도 라우팅 문제를 해결할 수 있습니다(실제로는 라우팅 테이블 203만 필요합니다). 레이아웃이 변경되면(예: 경로 컨테이너...) 이전에 추가할 필요가 없다고 생각되었던 경로를 다시 고려해야 합니다. 또한 항상 사용되지 않더라도 기본 경로는 기본 라우팅 테이블에 유지되어야 합니다. 이것이 "기본" 기본 경로가 됩니다. 기본 경로는 소스 IP 주소가 정의되지 않은 상태에서 서버가 클라이언트로 연결될 때 자동 선택에 영향을 줍니다.
ip route add table 201 default via 192.168.201.1 ip route add table 203 default via 192.168.203.1
소스 기반 규칙을 사용하여 선택합니다.
ip rule add from 192.168.201.232 lookup 201 ip rule add from 192.168.203.3 lookup 203
결과:
# ip route get from 192.168.203.3 192.168.1.30 192.168.1.30 from 192.168.203.3 via 192.168.203.1 dev enp11s0 table 203 uid 0 cache
아웃바운드 인터페이스가 다음으로 전환됩니다.enpu11s0라우팅 테이블 203을 사용합니다.
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3 local 192.168.203.3 from 192.168.1.30 dev lo table local cache <local> iif enp11s0
따라서 동일한 인터페이스에서 들어오는 패킷은 더 이상 SRPF(동일 인터페이스)에 실패하지 않습니다.
더 이상 서버 라우터가 복잡해지지 않습니다. 노트북의 핑은 두 주소 모두에서 작동합니다.
서버에서 소스 주소를 선택할 수 있는 클라이언트 애플리케이션은 트래픽이 선택한 경로를 간접적으로 변경합니다(예:
curl --interface 192.168.203.3 192.168.1.30
,ping -I 192.168.203.3 192.168.1.30
그러나 일반적으로ping -I enp11s0 192.168.1.30
변경하지 않음).오직이 설정의 이유는 여기에 자세히 설명되어 있습니다.SF Q&A내) 그러면 작동할 것이다.
참고: UDP 서비스
위 마지막 항목의 구성을 통해 TCP 서비스가 제대로 작동하게 됩니다. 그러나 BSD 소켓 API가 기본적으로 작동하는 방식 때문에 UDP에는 충분하지 않습니다.
수신 TCP 소켓이 모든 주소(INADDR_ANY: 0.0.0.0)에 바인딩되고 클라이언트 연결을 허용하는 accept(2)
경우 (사용새로운TCP 소켓이 자동으로 생성되고 쿼리된(로컬) 대상이 바인딩 주소로 선택됩니다. 새 TCP 소켓이 적절한 주소에 바인딩되므로 응답 시간에 해당 주소가 라우팅 스택에 소스 주소로 제공되고 위에서 설명한 대로 적절한 라우팅 규칙을 선택합니다. TCP All이 적합합니다.
UDP는 INADDR_ANY에 바인딩할 때 그렇게 간단하지 않습니다. 새 소켓이 자동으로 생성되지 않습니다.기본적으로쿼리가 작성된 위치를 알려주는 메커니즘이 없습니다. 따라서 응답은 TCP와 같이 올바른 소스 주소를 선택할 수 없습니다. OP의 경우 192.168.1.30에서 192.168.203.3으로 쿼리하면 애플리케이션에 사용 가능한 (로컬) 대상 192.168.203.3 정보가 없습니다. 라우팅 스택의 소스 주소 선택을 연기하기 위해 소스 주소를 바인딩하지 않고 응답합니다(예: INADDR_ANY/0.0.0.0으로 그대로 유지). 위의 라우팅 규칙은 선택되지 않으며 기본 라우팅 테이블의 기본 경로가 사용됩니다. 잘못된 경로는 192.168.203.3 대신 192.168.201.232를 응답 소스로 선택합니다. 이 응답이 랩톱에 도달하더라도(라우팅 관점과 SRPF 관점에서는 괜찮음) 랩톱 자체는 쿼리를 수행하기 위해 선택한 주소에서 오는 것이 아니기 때문에 이를 거부합니다.
멀티홈 환경의 서버 애플리케이션은 여러 피어에서 사용할 수 있으며 UDP에 대한 특별한 지원이 필요합니다. 이를 수행하는 두 가지 일반적인 방법이 있습니다.
INADDR_ANY 대신 각 서버의 주소에 개별적으로 바인딩
응답은 소켓의 바인딩 주소를 사용합니다. 쿼리가 도달했기 때문에이것소켓은 소켓이 응답 소스 주소로 사용할 동일한 대상 주소, 즉 클라이언트가 쿼리를 수행하고 애플리케이션 소켓이 바인딩되는 주소로 전송된다는 것을 의미합니다.
예를 들어 DNS 서버는 다음과 같습니다.바인딩 9동작: 서버의 모든 기존 주소에 개별적으로 바인딩됩니다.
socat
포트 1313에서 날짜 제공의 예:socat
바인딩할 각 주소에 대해 하나씩 세 가지 명령을 실행합니다.socat UDP4-LISTEN:1313,bind=127.0.0.1,fork EXEC:date & socat UDP4-LISTEN:1313,bind=192.168.201.232,fork EXEC:date & socat UDP4-LISTEN:1313,bind=192.168.203.3,fork EXEC:date &
소켓 옵션 사용IP_PKTINFO(또는 일부 *BSD에서는 IP_RCVDSTADDR) INADDR_ANY에 바인딩할 때
이를 위해서는 특정 애플리케이션 지원이 필요합니다.
connect(2)
또는read(2)
이러한write(2)
UDP 소켓에서는 더 이상 사용할 수 없지만 대신 소켓 옵션에서 제공하는 보조 메시지를 처리하고 다른 방법을 사용하여 쿼리 주소에 사용된 실제(로컬) 대상을 검색하는recvmsg(2)
기능sendmsg(2)
이 필요합니다. (에 설명되어 있음cmsg(3)
).예를 들어이것이 DNS 서버가 하는 일입니다속박되지 않은사용할 때
interface-automatic
옵션.socat
예(Linux:ip-pktinfo
, *BSD에서는 를 사용함ip-recvdstaddr
):socat -u \ UDP4-RECVFROM:1313,ip-pktinfo,reuseport,fork \ SYSTEM:'exec socat -u EXEC\:date UDP4-DATAGRAM\:$SOCAT_PEERADDR\:$SOCAT_PEERPORT\,bind=$SOCAT_IP_DSTADDR\:1313\,reuseport'
첫 번째
socat
는 수신 전용이고 두 번째는 방출 전용이며socat
첫 번째 환경 변수에서 사용할 수 있는 IP_PKTINFO 소켓 옵션에서 검색된 올바른 소스 주소로 응답하는 두 번째를 분기합니다. (SO_REUSEPORT)는 두 개의 "관련되지 않은" 소켓이 동일한 포트를 공유하도록 허용하는 해결 방법입니다(실제 응용 프로그램에서는 UDP 소켓이 복사되거나 전혀 복사되지 않고 직접 사용되기 때문에 이는 필요하지 않습니다).socat
reuseport
fork()
dup2(2)
답변2
모든 비링크 로컬 트래픽을 하나의 인터페이스를 통해 전송하지만 비링크 로컬 트래픽을 여러 인터페이스를 통해 수신하는 시스템에는 두 가지 문제가 있습니다.
(여기서 발생한) 첫 번째 문제는역방향 경로 필터링(바라보다 sysctl -ar '\.rp_filter'
). 이 기능은 기본적으로 활성화되어 있으며 응답하지 않는 전송 인터페이스의 패킷은 삭제됩니다(방화벽에 도달하기 전이라도). 따라서 0
수신 인터페이스로 설정해야 합니다 .
또 다른 문제는 방화벽이 트래픽의 절반만 보고 연결에 대해 모르기 때문에 응답 패킷을 삭제한다는 것입니다. 이 경우 고급 라우팅(정책 라우팅)이 필요합니다. man ip-rule
및 을 참조하세요 man ip-route
. 추가 라우팅 테이블을 설정하고 적절한 트래픽(나가는 패킷의 소스 주소)이 해당 라우팅 테이블을 사용하도록 해야 합니다. 이 작업이 완료되면 역방향 경로 필터링 문제가 자동으로 해결됩니다.