DIVERT(4)

명칭
divert - 커널에 의한 패킷 우회 메카니즘

서식
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> int socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)

해설

우회 소켓은 bind(2) 시스템 콜을 경유해 특정의 divert 포트에 바인드 할 수가 있는 것을 제외해, 생의 IP 소켓과 거의 같습니다. bind 에서의 IP 주소는 무시되어 포트 번호만이 의미를 가집니다. 우회 포트에 바인드 된 우회 소켓은, 어떤인가 (여기에서는 특정하지 않습니다)의 커널 메카니즘에 의해 그 포트에 우회 된 모든 패킷을 수신합니다. 패킷을 우회 포트에 기입할 수도 있습니다. 그 경우는 커널의 IP 패킷 처리에 다시 입력됩니다.

통상, 우회 소켓은 FreeBSD 의 패킷 필터링의 실장이나 ipfw(8) 프로그램과 함께 사용됩니다. 우회 소켓으로부터의 읽기나 기입에 의해, 합치하는 패킷을 호스트 머신을 경유할 때에 임의의 ``필터''를 통하거나 특별한 루팅의 세공을 실시한다고 했던 것(적)이 있습니다.

패킷을 읽는다
``들어 오는 패킷''에서 만나도 ``나가는 패킷''에서 만나도 우회 시킬 수가 있습니다. 입력 패킷은 IP 인터페이스상에서 수신된 후에 우회 됩니다. 출력 패킷은 다음의 호프에 전송 하기 전에 우회 됩니다.

우회 패킷은 read(2), recv(2), 혹은 recvfrom(2) 에 의해 그대로의 형태로 읽어낼 수가 있습니다. 후자의 경우에 얻을 수 있는 주소에서는, 포트 번호에는 패킷 우회자가 제공한데 등인가의 태그 (통상은 ipfw 의 룰 번호)(이)가 설정되어 IP주소부에는 입력 패킷의 경우는 패킷이 수신된 (최초의) 인터페이스 주소, 출력 패킷의 경우는 INADDR_ANY 하지만 설정됩니다. 입력 패킷의 경우는 주소에 계속되는 8 바이트안에 인터페이스명도 (거기에 들어가는 것으로서) 두어집니다.

패킷을 쓴다
우회 소켓에의 기입은 생의 IP 소켓에의 기입과 닮아 있습니다. 패킷은 ``그대로의''형태로 통상의 커널 IP 패킷 처리에 보내져 최소의 에러 체크만을 합니다. 패킷은 입력이라고 해도 출력이라고 해도 쓸 수가 있습니다. 즉 write(2) 혹은 send(2) 하지만 패킷의 배송에 사용되는지, sendto(2) 하지만 INADDR_ANY 의 행선지 IP 주소와 함께 사용되면(자), 패킷은 그것이 출력인것 같이 다루어집니다. 즉 로컬이 아닌 주소에 보낼 수 있습니다. 그 외의 경우는, 입력이라고 상정되어 모든 패킷 루팅이 실행됩니다.

후자의 경우에서는, 지정된 IP 주소는, 어떤 것인가의 로컬 인터페이스의 주소와 일치하는지, 인터페이스명이 IP 주소의 뒤에 발견되지 않으면 안됩니다. 만약 인터페이스명이 발견되면, 그 인터페이스가 사용되어 IP 주소의 값은 무시됩니다 (그것이 INADDR_ANY (이)가 아닌 것은 무시되지 않습니다). 이것은, 어느 인터페이스로부터 패킷이 ``도착''했는지를 나타내기 (위해)때문입니다.

통상, 입력으로서 읽어내지는 패킷은 입력으로서 쓰여지지 않으면 안됩니다. 출력 패킷에 대해서도 같습니다. 패킷을 읽어내고 써 되돌릴 때에는, recvfrom(2) 에 의해 주어진 소켓 주소와 같은 것을, 그대로의 형태로 sendto(2) 에 건네주는 것으로 사물이 단순하게 됩니다 (아래와 같이 참조).

sendto(2) 에 건네받는 소켓 주소의 포트 부분에는, 우회 모듈에 있어 의미가 있는 태그가 포함됩니다. ipfw(8) 의 경우에는, 태그는, 이 다음의 룰 번호로부터 룰 처리를 재개 해야 한다고 해석됩니다.

루프의 회피
우회 소켓에 ( sendto(2) (을)를 사용해) 기입해진 패킷은, 소켓 주소의 포트 부분에게 줄 수 있었던 태그에 계속되는 룰 번호로부터, 패킷 필터에 재입 됩니다. 통상, 소켓 주소는 우회를 발생시킨다 (같은 번호에 대해 몇개의 룰이 있는 경우는 다음의 룰은 아니다) 룰 번호에 대해 벌써 세트 되고 있습니다. 만약 '태그'가 다른 재입점을 나타내기 위해서(때문에) 옮겨놓을 수 있고 있으면, 같은 패킷이 같은 룰로 1 도 이상 우회 되는 것 같은 루프를 회피하기 위한 고려가 이루어져야 합니다.

상세
우회 소켓을 유효와 하기 위해서는, IPDIVERT 옵션을 지정해 커널을 컴파일 하지 않으면 안됩니다.

패킷은 우회 되지만 포트에 바인드 되는 소켓이 없는 경우, 혹은 IPDIVERT 하지만 커널에 대해 유효하게되어 있지 않은 경우는, 패킷은 버려집니다.

우회 되는 입력 패킷 fragment는 배송전에 모두 리아센불 됩니다. fragment가 1 개에서도 우회 되면(자) 모든 패킷이 우회 되게 됩니다. 만약, fragment의 몇개인가가 다른 포트에 우회 되면(자), 마지막에 어느 포트가 선택될까는 예기 할 수 없습니다.

패킷은 수신되어, 변경되지 않고 송신됩니다만, 출력으로서 쓰여진 패킷의 IP 헤더의 체크 섬은 올바른 값에 고쳐 쓸 수 있습니다. 입력으로서 쓰여져 잘못한 체크 섬을 가지는 패킷은 버려집니다. 그것들 이외는, 모든 헤더 필드는 변경되지 않습니다 (물론 네트워크에 닿은 차례로).

타입 SOCK_RAW 의 소켓의 생성과 같게, 1024 보다 작은 보트 번호를 바인드 하기 위해서는 슈퍼 유저 액세스가 필요합니다.

에러
생의 패킷의 기입시에 통상 발생하는 에러에 가세해 우회 소켓에의 기입은 이하의 에러를 돌려주는 일이 있습니다.

[EINVAL]
    패킷의 헤더가 부정한가, 패킷의 IP 옵션과 설정된 소켓의 옵션에 부정합이 있습니다.

[EADDRNOTAVAIL]
    행선지 주소에 포함되는 IP 주소는, INADDR_ANY (와)과 동일하지 않고, 어느 인터페이스에도 관련 지을 수 있고 있지 않습니다.

관련 항목
bind(2), recvfrom(2), sendto(2), socket(2), ipfw(8)

버그
이것은 유저 모드 프로세스가 어드레스 변환과 같은 여러가지 IP 의 세공을 실장하기 위한 상쾌한 방법을 제공하는 것을 시도한 것입니다. 그러나, 좀 더 깨끗이 시킬 수가 있겠지요 해, ipfw(8) 에 너무 의존하고 있습니다.

입력의 fragment가 우회의 전에 재구성되어야할 것인가 제발 에 대해서는 의문의 여지가 있습니다. 예를 들면, 다른 머신앞의 패킷 중 몇 개의 fragment가 로컬 머신 경유로 루팅 되지 않는 것뿐으로, 패킷이 없어집니다. 이것은 아마 어떠한 방법으로 설정 가능한 옵션으로 해야 합니다.

저자
Archie Cobbs <archie@whistle.com>, Whistle Communications Corp.