Eine Geschichte über den Betrieb von TUN / TAP, einem virtuellen Netzwerktreiber, der in der VPN-Implementierung von Python verwendet wird. Was ich beim Erstellen von https://github.com/kstm-su/dnsvpn überprüft habe.
Aus Wikipedia
TAP simuliert ein Ethernet-Gerät und manipuliert die Datenverbindungsschicht. TUN simuliert die Netzwerkschicht und manipuliert IP-Pakete und so weiter. TAP wird zur Brückengenerierung und TUN zum Routing verwendet.
Vom Betriebssystem an ein TUN / TAP-Gerät gesendete Pakete werden an das mit diesem Gerät verbundene Anwenderprogramm gesendet. Sie können auch Pakete von Ihrem Programm an das TUN / TAP-Gerät senden. In diesem Fall leitet das TUN / TAP-Gerät diese Pakete an den OS-Protokollstapel weiter, sodass es so aussieht, als ob die Pakete von außen von der OS-Seite empfangen wurden.
Wenn Sie von L3 oder höher verarbeiten möchten, verwenden Sie TUN, und wenn Sie von L2 verarbeiten möchten, verwenden Sie TAP.
Mac Kann mit Gebräu installiert werden.
$ brew cask install tuntap
Es ist in Ordnung, wenn unter "/ dev" "tun [0-15]" und "tippen [0-15]" stehen.
Linux Wenn der Kernel 2.2.x, 2.4.x oder höher ist, sollte er standardmäßig enthalten sein
$ lsmod | grep tun
Wenn nichts herauskommt, modprobe
$ sudo modprobe tun
Alles was Sie brauchen ist / dev / net / tun
.
Machen Sie TUN / TAP mit ip link
sichtbar.
Grundsätzlich öffnen Sie die Gerätedatei nur mit "open", aber unter Linux müssen Sie den Gerätenamen und das Flag mit "ioctl" setzen, was etwas problematisch ist.
Wenn das Programm endet, ist das Gerät nicht registriert, sodass das Beispielprogramm nicht in einer Endlosschleife endet.
Mac
Öffnen Sie einfach / dev / tun *
und es ist einfach.
(/ Dev / tap *
bei Verwendung von TAP)
# tuntap-darwin.py
import os
import time
tun = os.open('/dev/tun0', os.O_RDWR)
while True:
time.sleep(1)
Wenn Sie es ausführen, können Sie sehen, dass der Name der Gerätedatei als der Name des Netzwerkgeräts erkannt wird.
$ sudo python tuntap-darwin.py &
$ ip link show tun0
tun0: flags=8850<POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1500
open (pid 2251)
Linux
Öffnen Sie / dev / net / tun
und verwenden Sie ioctl
, um TUN oder TAP oder den Gerätenamen einzustellen.
Wenn Sie TAP verwenden, setzen Sie TUN_TUN_DEV
=> TUN_TAP_DEV
.
# tuntap-linux.py
import os
import time
import fcntl
# https://github.com/kstm-su/dnsvpn/blob/master/lib/linux.py
import linux
tun = os.open('/dev/net/tun', os.O_RDWR)
ifr = linux.ifreq(name=b'hoge', flags=linux.IFF_NO_PI|linux.TUN_TUN_DEV)
fcntl.ioctl(tun, linux.TUNSETIFF, ifr)
while True:
time.sleep(1)
Wenn Sie es ausführen, können Sie sehen, dass es die Zeichenfolge erkennt, die an das Argument "name" von "ifreq" als Name des Netzwerkgeräts übergeben wurde.
$ sudo python tuntap-linux.py &
$ ip addr show hoge
6: hoge: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 500
link/none
Versuchen Sie, Daten mit dem registrierten TUN / TAP-Gerät zu senden und zu empfangen. Empfangen Sie auf Mac und Linux einfach mit "Lesen" und senden Sie mit "Schreiben". Wenn Sie jedoch so wie es ist "lesen" oder "schreiben", werden Sie wütend. Führen Sie daher einen externen Befehl aus, um eine Verbindung herzustellen.
# tuntap.py
import os
import subprocess
tun = os.open('/dev/tun0', os.O_RDWR)
subprocess.check_call('sudo ifconfig tun0 192.168.100.2 192.168.100.1 netmask 255.255.255.0 up', shell=True)
while True:
data = os.read(tun, 1500)
print(data)
os.write(tun, data)
Versuchen Sie, auf dem von Ihnen erstellten Netzwerkgerät "ping" einzugeben
$ sudo python3 tuntap.py &
$ ping 192.168.100.1
PING 192.168.100.1 (192.168.100.1): 56 data bytes
b'E\x00\x00Tj\x15\x00\x00@\x01\xc7?\xc0\xa8d\x02\xc0\xa8d\x01\x08\x00t\xa4\x7f\x0e\x00\x00XA\xcbh\x00\x07\xf5\x98\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
Request timeout for icmp_seq 0
b'E\x00\x00T~\xa2\x00\x00@\x01\xb2\xb2\xc0\xa8d\x02\xc0\xa8d\x01\x08\x00dk\x7f\x0e\x00\x01XA\xcbi\x00\x08\x05\xcf\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
Request timeout for icmp_seq 1
b'E\x00\x00T\xa3\x8e\x00\x00@\x01\x8d\xc6\xc0\xa8d\x02\xc0\xa8d\x01\x08\x00b7\x7f\x0e\x00\x02XA\xcbj\x00\x08\x08\x01\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
Request timeout for icmp_seq 2
b'E\x00\x00T2\x86\x00\x00@\x01\xfe\xce\xc0\xa8d\x02\xc0\xa8d\x01\x08\x00P\xf3\x7f\x0e\x00\x03XA\xcbk\x00\x08\x19C\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
Bei Wireshark werden für jeden Ping zwei angezeigt. Dies liegt daran, dass das empfangene Paket so gesendet wird, wie es ist.
Recommended Posts