iptables, ipchains 및 ipfw에 대한 프로그래밍 인터페이스의 역사

Sep 04 2020

iptables최근에 Go의 규칙 을 조작해야했고 , docker 와 coreos의 래퍼 라이브러리 exec()가 모두 iptables명령 을 내리고 화면이 표준 출력을 긁어내는 것을 발견했습니다. 이것은 나에게 놀라운 것 같았습니다.

Python-land에는 python-iptables가 있습니다 .

iptables와의 상호 운용성은 iptables 바이너리를 호출하고 출력을 파싱하지 않고 iptables C 라이브러리 (libiptc, libxtables 및 iptables 확장)를 사용하여 달성됩니다.

Python 라이브러리는 런타임에 C 라이브러리를로드 할 수 있고 Go는 [편집 : 틀 렸습니다],하지만 Go는 해당 라이브러리에 정적으로 링크 할 수 없습니까? Go 라이브러리는 libxtables.a어딘가에서 등을 가져와야 하기 때문에 ? ( 데비안 dpkg -L에서 관련 -dev패키지를 사용 중이며 .sos 만 표시 됩니다.)

어쨌든, Netfilter FAQ 에 따르면 :

4.5 규칙 추가 / 제거를위한 C / C ++ API가 있습니까?

안타깝게도 대답은 아니오입니다.

이제 '하지만 libiptc는 어떨까요?'라고 생각할 수 있습니다. 메일 링리스트 (들)에서 여러 번 지적했듯이 libiptc는 결코 공용 인터페이스로 사용 되지 않았습니다 . 우리는 안정적인 인터페이스를 보장하지 않으며 다음 리눅스 패킷의 구현에서 제거 할 예정입니다.

우리는 그러한 API에 근본적인 부족이 있음을 잘 알고 있으며 그 상황을 개선하기 위해 노력하고 있습니다. 그때까지는 system ()을 사용하거나 iptables-restore의 stdin에 파이프를 여는 것이 좋습니다. 후자는 더 나은 성능을 제공합니다. libiptc는 어쨌든 합리적으로 사용하기에는 너무 낮은 계층입니다.

좋아, 그래서 아마도 당신은 그 C 라이브러리를 안정된 것으로 취급해서는 안됩니다. 그러다가 "그냥 /proc직접 얘기 해보면 어떨까요?" , 알고 보니 iptables대부분 사용하지 않는 /proc커널 (단지 테이블 이름을 읽을?) 얘기로, 메인 인터페이스는 실제로 getsockopt()및 setsockopt()언 바운드 소켓.

이것은 또 다른 놀라움이었습니다! (하지만 커널과 인터페이스하는 재미있는 방법처럼 보이는 이런 종류의 코드에 익숙하지 않기 때문일 수 있습니다.)

나는에서 고고학 뒤쪽의 조금 한 iptables에 ipchains에 ipfw와 발견 1997 IPFW 사람 페이지 나 더 조금 느낌 :

BUGS
       The  setsockopt(2)  interface  is a crock.  This should be
       put under /proc/sys/net/ipv4 and the world would be a bet-
       ter place.

다른 곳에서 "ipfw 유틸리티는 FreeBSD 2.0에서 처음 등장했습니다"와

HISTORY
      Initially this utility was written for BSDI by:
       Daniel Boulet    <[email protected]>
      The FreeBSD version is written completely by:
       Ugen J.S.Antsilevich <[email protected]>
      while synopsis partially compatible with old one.

다음 ipfw은 1994 년 의 FreeBSD 2.0 버전입니다 . 여전히 사용 setsockopt()하지만 kvm_read()대신 사용 하는 것 같습니다 getsockopt().

내 질문

  • 위에서 잘못 말한 것을 수정하십시오 :)
  • {get,set}sockopt()애초에 그들이 선택한 이유는 무엇 입니까? 흔하지 않은가요, 아니면 그냥 새로운가요?
  • 왜 어떤 시점에서 변경되지 않았습니까? /proc1997 man 페이지에서 제안한 것처럼 아래 에있는 것을 좋아 합니다.
  • 왜 그들은 안정 / 공개 C 인터페이스를 만들지 않았 iptables습니까?

내 후속 질문

"정답이 아닙니다. 기본 인터페이스는 netlink의 NETLINK_NETFILTER 제품군입니다."

이 포인터에 감사드립니다!

나는보고있다 https://git.netfilter.org/iptables/tree단지 libipq내가 뭔가를 누락하지 않는 한 넷 링크 소켓을 사용하는 것으로 보인다.

$ ick "socket\("
include/libiptc/libiptc.h
158:int iptc_get_raw_socket(void);

include/libiptc/libip6tc.h
152:int ip6tc_get_raw_socket(void);

utils/nfsynproxy.c
129:    fd = socket(AF_INET, SOCK_STREAM, 0);

libiptc/libiptc.c
1312:   sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);

extensions/libxt_set.h
14: int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

libipq/libipq.c
223:                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
225:                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);

libxtables/xtables.c
881:    sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);

libipq나에게 물건 외모 "정상은"소켓을 바인드 그것 SOCKADDR와, sendto(), recvfrom(), 등

또한 netlink 작업을 수행 xtables-monitor하는 mnl_socket_*래퍼를 사용하는 것 같습니다 .

그러나 나는 알아낼 수 없습니다 libiptc및 xtables- 넷 링크에 대한 언급을하고, 그들은 심지어 바인드 소켓하지 않습니다.

https://git.netfilter.org/iptables/tree/libxtables/xtables.c#n881

https://git.netfilter.org/iptables/tree/libiptc/libiptc.c#n1312

mozilla의 rr 디버거에서 가져온 다음 코드와 같이 netlink를 사용하지 않는 다른 예가 있습니다. https://github.com/mozilla/rr/blob/master/src/test/netfilter.c

그리고 netlink는 2000 년 (2.2)부터 Linux 전용이며, {get,set}sockopt()(적어도) 의이 항목 ipfw은 BSD-land에 있습니다.

더 이상 내 질문이 무엇인지 잘 모르겠습니다. :) non-netlink 소켓이 어떻게 든 bind()sockaddr 없이 올바른 커널 쪽과 통신 합니까?

답변

StephenKitt Sep 04 2020 at 20:22

Python 라이브러리는 런타임에 C 라이브러리를로드 할 수 있지만 Go는

Go 는 공유 C 라이브러리를 사용할 수 있습니다.

, 알고 보니 iptables대부분 사용하지 않는 /proc커널 (단지 테이블 이름을 읽을?) 얘기로, 메인 인터페이스는 실제로 getsockopt()하고 setsockopt().

{get,set}sockopt()애초에 그들이 선택한 이유는 무엇 입니까? 흔하지 않은가요, 아니면 그냥 새로운가요?

(이 대답은 이전에 기본 인터페이스가 netlink'의 NETLINK_NETFILTER가족 이라고 잘못 언급했습니다 .)

맞습니다 . 적절한 유형의 바인딩되지 않은 소켓에 대한 iptables호출을 사용 getsockopt하여 커널과 상호 작용하여 결국 커널의 netfilter코드를 호출 합니다 . 나는 이것이 역사적인 이유라고 생각합니다 ...

덧붙여, getsockopt및 setsockopt언 바운드을 포함하여 국가의 다양한에서 소켓 작업, 그리고 그들이 연결하기 전에 설정 옵션을 사용하고 있기 때문에해야합니다. netfilter-via- sockopt연결 효과적으로 사이드 채널이다.

왜 어떤 시점에서 변경되지 않았습니까? /proc1997 man 페이지에서 제안한 것처럼 아래 에있는 것을 좋아 합니다.

여러 가지 이유가있을 수 있지만 하나는 의심 할 여지없이 이전 버전과의 호환성입니다. Linux에서는 사용자 공간 인터페이스가 중단되지 않아야합니다. 따라서 새 인터페이스가 제공 될 수 있지만 기존 인터페이스는 그대로 유지되므로 개선하거나 이미 작동하는 프로그램을 다시 작성하려는 인센티브가 줄어 듭니다.

iptables명령 줄 도구를 너무 많은 노력없이 사용할 수 있고 더 나은 인터페이스를 제공하는 데 더 많은 노력이 필요 하다면 변경이 어려울 것입니다. 적절하게 관리되는 libiptc스타일의 라이브러리도 가능했지만 iptables개발자가 그렇게 할 수 있는 인센티브는 많지 않았습니다 .

왜 그들은 안정 / 공개 C 인터페이스를 만들지 않았 iptables습니까?

"그들"은 그것에 대해 결코 이해하지 못했기 때문입니다. 지금 iptables에 찬성하여 단계적으로 폐지되고 nftables추상화의 서로 다른 수준의 액세스를 제공하는 라이브러리들을 포함하고, ( libnftables, libnftnl, libnfnetlink). 이것은 netlink커널과 사용자 공간 사이에 정보를 전송하기 위해 소켓 기반 인터페이스로 설계된를 사용하며 nftables(및 iptables) 과 같은 도구에 자연스럽게 적합합니다 . netlink문서 목록 사용할 수있는 다른 가족; 여기에는 상당히 많은 커널 호스팅 기능이 포함됩니다. netlink.

당신은 찾을 수 있습니다 https://github.com/vishvananda/netlinkiptablesGo에서 운전 을 시작하는 데 유용 합니다. (상당한 양의 작업이 필요하지만 처음부터 시작하는 것보다 낫습니다.)