Linux를 사용하여 전송되는 이더넷 인터페이스 데이터를 지정하는 방법

StackOverflow https://stackoverflow.com/questions/172905

  •  05-07-2019
  •  | 
  •  

문제

동일한 서브넷에 두 개의 네트워크 인터페이스가있는 Linux 기반 서버 시스템에서 작업 중입니다 (지금은 172.17.32.10 & 172.17.32.11). 네트워크의 호스트에 데이터를 보내면 데이터가 전송되는 서버의 인터페이스를 지정하고 싶습니다. 소프트웨어에서 한 인터페이스에서 다른 인터페이스에서 다른 인터페이스 (또는 둘 다를 전송할 수도 있음)로 전환 할 수 있어야합니다 (이 응용 프로그램에는 정적 라우팅 규칙이 작동하지 않습니다).

StackoverFlow에서 NetLink 라이브러리를 사용하여 즉시 경로를 수정하는 관련 질문을 찾았습니다. 이것은 직관적으로 작동하는 것처럼 보이지만 동일한 결과를 달성 할 다른 옵션이 있는지 궁금합니다.

도움이 되었습니까?

해결책

범죄는 의도하지 않았지만 bind ()를 사용하는 것에 대한 답은 잘못되었습니다. Bind ()는 패킷 IP 헤더 내에있는 소스 IP 주소를 제어합니다. 패킷을 보내는 데 사용되는 인터페이스를 제어하지 않습니다. 커널의 라우팅 테이블을 참조하여 특정 대상에 도달하는 데 가장 적은 비용이있는 인터페이스를 결정합니다. (*참고 참조)

대신, 당신은 an을 사용해야합니다 SO_BINDTODEVICE 양말. 이것은 두 가지를 수행합니다.

  • 패킷은 커널 라우팅 테이블의 말에 관계없이 지정한 인터페이스에서 항상 방출됩니다.
  • 지정된 인터페이스에 도착하는 패킷 만 소켓에 건네집니다. 다른 인터페이스에 도착하는 패킷은 그렇지 않습니다.

사이에 전환하려는 여러 인터페이스가있는 경우 인터페이스 당 하나의 소켓을 작성하는 것이 좋습니다. 또한 묶인 인터페이스에 패킷 만 받기 때문에 이러한 소켓을 모두 추가해야합니다. select()/poll()/당신이 무엇을 사용하는지.

#include <net/if.h>

struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
            (void *)&ifr, sizeof(ifr)) < 0) {
    perror("SO_BINDTODEVICE failed");
}

(*노트)Bind() 인터페이스 IP 주소는 혼란 스럽지만 올바른 동작으로 이어질 수 있습니다. 예를 들어 당신이 bind() ETH1의 IP 주소로, 라우팅 테이블은 패킷을 ETH0으로 전송하면 패킷이 ETH0 와이어에 나타나지 만 ETH1 인터페이스의 소스 IP 주소를 전달합니다. ETH1 IP 주소로 전송 된 패킷은 ETH1로 다시 라우팅됩니다. 두 개의 IP 인터페이스가있는 Linux 시스템을 사용 하여이 테스트 할 수 있습니다. 나는 하나가 있고 그것을 테스트했고 bind() 패킷을 물리적 인터페이스로 조종하는 데 효과적이지 않습니다.

기술적으로 허용되지만 토폴로지에 따라 그럼에도 불구하고 이것은 작동하지 않을 수 있습니다. 공격자가 단조 IP 소스 주소를 사용하는 분산 거부 공격 거부 공격을 약화시키기 위해 많은 라우터가 이제 RPF (Reverse Path Forwarding) 점검을 수행합니다. "잘못된"경로에 소스 IP 주소가있는 패킷을 삭제할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top