최근에 나는 Go의 규칙을 만지작거려서 iptables
알아차렸습니다.부두 노동자의그리고핵심래퍼 라이브러리는 명령 exec()
으로 출력 iptables
하고 화면은 표준 출력을 가져옵니다. 나는 이것이 나를 놀라게 했다.
파이썬 세계에는파이썬 iptables:
iptables 바이너리를 호출하고 출력을 구문 분석하는 대신 iptables C 라이브러리(libiptc, libxtables 및 iptables 확장)를 사용하여 iptables와의 상호 운용성을 달성합니다.
내 생각엔 Python 라이브러리가 C 라이브러리를 런타임에 로드할 수 있도록 허용하는 것 같지만 Go는 [편집: 제가 틀렸습니다]. 하지만 Go가 이러한 라이브러리에 정적으로 링크할 수는 없나요? Go 라이브러리는 libxtables.a
어딘가에서 얻어야 하기 때문에? (Debian에서 관련 패키지를 찾고 있는데 dpkg -L
s만 보입니다.)-dev
.so
어쨌든 따르면웹 필터 FAQ:
4.5 규칙을 추가/제거하기 위한 C/C++ API가 있습니까?
불행히도 대답은 '아니요'입니다.
이제 "하지만 libiptc는 어떻습니까?"라고 생각할 수도 있습니다. 메일링 리스트에서 여러 번 지적했듯이 libiptc는안 돼요공용 인터페이스로 사용하기 위한 것입니다. 우리는 안정적인 인터페이스를 보장하지 않으며 다음 버전의 Linux 패킷에서 이를 제거할 계획입니다.
우리는 이러한 API에 근본적인 결함이 있다는 것을 잘 알고 있으며, 상황을 개선하기 위해 열심히 노력하고 있습니다. 그때까지는 system()을 사용하거나 iptables-restore의 표준 입력으로 파이프를 여는 것이 좋습니다. 후자는 더 나은 성능 필터링을 제공합니다. 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()
왜 그들은 처음에 그것을 선택했습니까? 이것이 특이한 것입니까, 아니면 나에게 새로운 것입니까?- 왜 어느 시점에는 변하지 않았습니까?
/proc
1997 매뉴얼 페이지에서 제안하는 것과 같습니다 . - 왜 그들은 안정적인/공용 C 인터페이스를 생각해내지 못했을까요
iptables
?
내 후속 질문
"정확히는 아닙니다. 기본 인터페이스는 netlink의 NETLINK_NETFILTER 제품군입니다."
이 팁을 제공해 주셔서 감사합니다!
내가보고 있어요https://git.netfilter.org/iptables/tree그리고 libipq
뭔가 빠진 것이 없다면 netlink 소켓만 사용되는 것 같습니다.
$ 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()
네트워크 링크 작업을 수행하는 데 사용되는 래퍼 xtables-monitor
도 있는 것 같습니다 .mnl_socket_*
그러나 나는 그것을 알아낼 수 없습니다 libiptc
. xtables
netlink에 대한 언급이 없으며 소켓을 바인딩하지도 않습니다.
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
2000년(2.2) 현재, netlink는 {get,set}sockopt()
(적어도) ipfw
더 오래된 BSD 영역인 Linux에서만 사용할 수 있습니다.
bind()
더 이상 내 문제가 무엇인지 잘 모르겠습니다 :) netlink가 아닌 소켓이 어떻게 sockaddr 없이 올바른 커널 측과 통신할 수 있습니까?
답변1
내 생각에 Python 라이브러리는 런타임에 C 라이브러리를 로드할 수 있지만 Go는 그렇지 않습니다.
가다할 수 있는공유 C 라이브러리를 사용하십시오.
iptables
대부분의 경우 커널과 통신하는 데 사용되지 않으며 (/proc
테이블 이름만 읽으나요?) 기본 인터페이스는 실제로getsockopt()
및 입니다setsockopt()
.
{get,set}sockopt()
왜 그들은 처음에 그것을 선택했습니까? 이것이 특이한 것입니까, 아니면 나에게 새로운 것입니까?
(이 답변은 이전에 기본 인터페이스가 다음과 같다고 잘못 명시했습니다.netlink
가족 NETLINK_NETFILTER
. )
당신 말이 맞습니다. 적절한 유형의 바인딩되지 않은 소켓에 대한 호출을 iptables
사용하여 getsockopt
커널과 상호 작용하고 궁극적으로커널 netfilter
코드. 나는 이것이 역사적인 이유라고 생각합니다 ...
그런데 바인딩 해제를 포함하여 다양한 상태의 소켓에서 작업 getsockopt
하며 setsockopt
연결하기 전에 옵션을 설정하는 데 사용되기 때문에 이 작업을 수행해야 합니다. -via- netfilter
연결은 sockopt
실제로는 부채널입니다.
왜 어느 시점에는 변하지 않았습니까?
/proc
1997 매뉴얼 페이지에서 제안하는 것과 같습니다 .
여러 가지 이유가 있을 수 있지만 그 중 하나는 의심할 여지 없이 이전 버전과의 호환성입니다. Linux에서는 사용자 공간 인터페이스가 절대로 손상되어서는 안 됩니다. 따라서 새로운 인터페이스가 제공될 수 있지만 기존 인터페이스는 그대로 유지되므로 인터페이스를 개선하거나 이미 실행 중인 프로그램을 다시 작성하려는 인센티브가 줄어듭니다.
명령줄 도구를 적은 노력으로 사용할 수 있고 더 나은 인터페이스를 제공하려면 더 많은 노력이 필요한 한 iptables
변경은 어려울 것입니다. 적절하게 유지 관리되는 libiptc
스타일 라이브러리도 가능했지만 개발자는 iptables
그렇게 할 동기가 별로 없었습니다.
왜 그들은 안정적인/공용 C 인터페이스를 생각해내지 못했을까요
iptables
?
왜냐하면 "그들"은 문제를 해결하지 못했기 때문입니다. 이제 iptables
단계적으로 폐지됨nftables
, 여기에는 다양한 추상화 수준에서 액세스를 제공하는 여러 라이브러리( libnftables
, libnftnl
, )가 포함되어 있습니다. 커널과 사용자 공간 간에 정보를 전송하기 위한 소켓 기반 인터페이스로 설계된 를 libnfnetlink
사용하며 ( 및 ) 와 같은 도구 에 매우 적합합니다. 문서 에는 사용 가능한 다른 제품군이 나열되어 있으며 여기에는 상당한 커널 호스팅 기능이 포함되어 있습니다. .netlink
nftables
iptables
netlink
netlink
당신은 찾을 수 있습니다https://github.com/vishvananda/netlinkiptables
Go에서 운전할 때 유용합니다. (이것은 많은 작업이 필요하지만 처음부터 시작하는 것보다 낫습니다.)