저는 완전히 멍청한 놈입니다. 이것은 커널 네트워킹에 대한 최초의 실험입니다. 두 인터페이스 사이에 브리지를 만들고 tap
트래픽을 보내려고 합니다. 이는 특정 목적이라기보다는 실험에 가깝습니다.
$ brctl showstp br0
br0
bridge id 8000.46846e0c0ff9
designated root 8000.46846e0c0ff9
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 1.98 tcn timer 0.00
topology change timer 0.00 gc timer 115.04
flags
tap1 (1)
port id 8001 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8001 forward delay timer 10.34
designated cost 0 hold timer 0.98
flags
tap2 (2)
port id 8002 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.98
flags
br0
두 가지를 모두 tap1
추가 하여 다리를 만들었습니다 tap2
. ARP 패킷을 tap1
사용 하여 ARP 패킷을 주입하는 프로그램이 있습니다 libpcap
. Wireshark는 tap1
. 그러나 에는 패킷이 표시되지 않습니다 tap2
. ebtables에 다음 규칙을 추가해 보았습니다.
sudo ebtables -I INPUT --log --log-level debug
로그에 패킷이 표시되지 않습니다. 어떤 의견이라도 감사하겠습니다.
편집: 더 많은 정보를 추가합니다. 가짜 패킷을 주입하는 것이 실제로 응용 프로그램입니다. 여기서 나의 의도는 VM 없이 완전히 소프트웨어에서 패킷이 Linux 커널 스택을 통해 전달되는 방식을 시뮬레이션하는 것입니다. 새로운 네트워크 네임스페이스를 생성하지 않습니다. 아마도 그게 문제일까요?
프로세스가 두 개뿐입니다. "읽기" 프로세스에는 파일 설명자가 열려 있으며 tap2
계속해서 읽으려고 시도합니다. 쓰기 프로세스에는 파일 설명자가 열려 tap1
있으며 ARP 쿼리를 보내라는 사용자 프롬프트를 기다립니다. ARP 쿼리에는 임의의 소스 IP 주소가 있습니다. 소스 MAC 주소는 의 MAC 주소로 설정됩니다 tap1
. tcpdump의 출력은 다음과 같습니다.
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
0x0000: ffff ffff ffff ba9c 0589 16ad 0806 0001
0x0010: 0800 0604 0001 ba9c 0589 16ad 0000 f811
0x0020: 0000 0000 0000 0808 0808
IP 주소를 구성했지만 IP 주소가 없도록 구성 tap1
했습니다 . tap2
그게 문제일까요?
brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up
답변을 토대로 다양한 어플리케이션을 에 첨부해 보았는데요 tap2
. 나는 이것을 발견했습니다: tap1
또는 를 사용하는 애플리케이션이 없으면 tap2
두 인터페이스 모두 LOWER_UP 플래그가 설정되어 있지 않습니다.
4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
애플리케이션을 시작하면 LOWER_UP 플래그가 설정됩니다.
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
내용이 길어져서 죄송합니다. 문제를 이해하는 데 충분한 정보가 있기를 바랍니다.
답변1
만약에 당신이 완전히 멍청하다고 말했기 때문에, tun(레이어 3) 또는 탭(레이어 2) 인터페이스는 애플리케이션의 네트워크 인터페이스 끝점이며 애플리케이션은 이 네트워크 인터페이스에서 패킷을 읽고 쓸 수 있습니다. 당신이 만든 것 ip tuntap add ...
또는 오래된 tunctl
것은영구 이름이러한 엔드포인트의 경우 일반적으로 애플리케이션을 계속 실행하며 애플리케이션을 실행하지 않는 한 아무 작업도 수행하지 않습니다.
응용 프로그램은 설계상 네트워크 인터페이스와 상호 작용하므로 제가 설명한 정상적인 상호 작용을 "주입"하지 않는 한 제3자 응용 프로그램에 패킷을 "주입"할 필요가 없습니다.
또한 네트워킹을 가지고 놀고 싶다면 다음을 사용하는 것이 좋습니다.네트워크 네임스페이스그리고베스 쌍. 기본적으로 네트워크에 있는 실제 컴퓨터 간의 통신을 모방할 수 있는 많은 가상 컴퓨터를 컴퓨터에 설정할 수 있습니다.
따라서 그렇게 하고 싶지만 자신의 애플리케이션에서 패킷을 생성하고 수신하는 작업을 수행하고 싶지 않다면 tun/tap 인터페이스가 필요하지 않습니다.
즉, 방금 패킷을 "주입"하는 데 사용하는 것을 말하지 않았기 때문에 약간의 변형을 사용하여 설정을 테스트했습니다. 두 개의 를 사용하여 끝점 과 socat
탭을 생성한 다음 이를 연결하고 다른 두 개의 를 사용했습니다. 나에게 맞는 패킷을 생성하려면 두 개의 서로 다른 네임스페이스가 필요합니다. 로컬 패킷은 항상 루프백을 통해 전달되므로 다른 네임스페이스에 있어야 합니다 .tap0a
tap1a
socat
lo
그리고 예상한 대로 브리징 탭 장치가 제대로 작동합니다.
그래서 나는 당신이 주입하고 있는 패킷에 문제가 있다고 가정합니다. 잘못된 이더넷 주소이거나 브로드캐스트가 없습니다. tcpdump -xx ...
ARP 패킷을 주입할 때 출력 으로 질문을 편집하십시오 .
아니면 네트워크 네임스페이스를 생성하고 대신 두 개의 veth-pair의 두 끝점을 연결하고 싶습니까? 훨씬 간단합니다.
편집하다
ARP 패킷이 좋아 보입니다. 에 연결된 애플리케이션이 없는 것 같습니다 tap2
. 그렇게 하면 에 대한 플래그가 ip link
표시되지 않습니다 . 추측: 브리지는 장치가 부분적으로만 작동하고 있음을 감지하고 이 포트로 패킷을 보내지 않습니다.LOWER_UP
tap2
tap
그걸로 바꿔보세요가지다다음과 같은 애플리케이션이 연결되어 있습니다.
sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C
( 10.0.2.2/24
주소는 아무 작업도 수행하지 않지만 socat
주소를 지정하지 않으면 작동하지 않습니다) 및 다른 터미널에서
sudo ip link set tapx master br0
(대체 brctl addif
) 그런 다음 패킷을 여러 번 주입하고 첫 번째 창에서 hexdump를 얻는지 확인합니다. 또한 으로 확인 LOWER_UP
하십시오 ip link show dev tapx
.
BTW, ifconfig
구식 brctl
입니다. 대신 ip
및를 사용하세요 bridge
.
브리지 포트에 IP 주소를 할당하지 않아도 문제가 되지 않습니다. 왜냐하면 브리지 포트IP 주소가 없습니다(브리지의 노예가 되기 전에 할당된 일부가 있는 경우 무시됩니다.) 예를 참조하십시오여기.
답변2
나는 이것으로 많은 어려움을 겪었고 해결책에 도달했다고 생각합니다. 아니면 적어도 무슨 일이 일어나고 있는지 더 잘 이해하게 될 것입니다.
수신측("RX")의 탭 인터페이스에 패킷을 전달하는 유일한 방법은 해당 패킷을 소켓 설명자에 쓰는 것임을 명심하는 것이 중요합니다.탭을 연 프로세스에 의해 생성됨( open("/dev/net/tun",...)
및 을 통해 ioctl
). 한 번에 하나의 프로세스만 이 파일 설명자를 가질 수 있습니다. 탭 장치가 열려 있고 다른 프로세스가 동일한 이름을 가진 다른 탭 장치를 다시 열려고 하면 해당 시스템 호출이 실패합니다.
따라서 Wireshark와 같은 다른 프로세스가 있는 경우 원시 소켓을 연 다음 바인딩합니다.저것에는 tap0
트래픽 쓰기만 가능합니다.밖으로(커널의 관점에서) 시스템의. 즉, Wireshark는 TX
의 카운터를 범핑해야 하며 패킷 tap0
만 RX
브리지 인터페이스로 전달됩니다.
다음과 같이 각각의 카운터를 확인할 수 있습니다.
#!/bin/bash
for if in tap{0,1}; do
stats=/sys/class/net/$if/statistics/
rx=$(cat $stats/rx_packets)
tx=$(cat $stats/tx_packets)
echo "$if: rx=$rx, tx=$tx"
done
다음과 같은 결과가 출력됩니다.
tap0: rx=0, tx=6
tap1: rx=0, tx=5
따라서 귀하의 특정 경우에는 문제가 여기에 있다고 생각됩니다.
ARP
libpcap을 사용 하여 패킷을 주입하는 프로그램이 있습니다tap1
. Wireshark는tap1
. 그러나 에는 패킷이 표시되지 않습니다tap2
.
tap1에 ARP 패킷을 어떻게 주입합니까? Wireshark가 및를 호출하지 않는다고 가정 fd = open("/dev/net/tun", ...)
하므로 ioctl(fd, TUNSETIFF, ...)
전송된 패킷은 TX이므로 브리지되지 않습니다.
해당 패킷이 전달되고 표시 되도록 하려면 의 파일 설명자 tap0
에 패킷을 쓰기 위해 여는 프로그램이 필요합니다 .tap0
br0
tap1