Verwenden Sie TUN / TAP mit Python

Überblick

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.

Voraussetzungen

Über TUN / TAP

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.

TUN / TAP-Installation

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.

Registrieren Sie ein TUN / TAP-Gerät

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

Kommunizieren Sie mit TUN / TAP

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. スクリーンショット 2016-12-03 4.32.29.png

Recommended Posts

Verwenden Sie TUN / TAP mit Python
[Python] Verwenden Sie JSON mit Python
Verwenden Sie Mecab mit Python 3
Verwenden Sie DynamoDB mit Python
Verwenden Sie Python 3.8 mit Anaconda
Verwenden Sie Python mit Docker
Verwenden Sie die Trello-API mit Python
Verwenden Sie die Twitter-API mit Python
Verwenden Sie die Unterschall-API mit Python3
Python: So verwenden Sie Async mit
Verwenden Sie eine Point Grey-Kamera mit Python (PyCapture2).
Verwenden Sie vl53l0x mit RaspberryPi (Python)
Verwenden Sie NAIF SPICE TOOL KIT mit Python
Verwenden Sie rospy mit virtualenv in Python3
Verwenden Sie Python in pyenv mit NeoVim
Verwenden Sie die Windows 10-Sprachsynthese mit Python
Verwenden Sie OpenCV mit Python 3 in Window
Verwenden Sie PostgreSQL mit Lambda (Python + psycopg2)
FizzBuzz in Python3
Scraping mit Python
Statistik mit Python
Verwenden Sie smbus mit python3 in einer pyenv-Umgebung
Verwenden Sie DeepL mit Python (für die Artikelübersetzung)
Scraping mit Python
Python mit Go
Verwenden Sie den Amazon Simple Notification Service mit Python
Twilio mit Python
In Python integrieren
Spielen Sie mit 2016-Python
[Einführung in Python] Verwenden wir foreach mit Python
Verwenden Sie PIL oder Pillow mit Cygwin Python
AES256 mit Python
Verwenden Sie die Verschlüsselung der Verschlüsselungsbibliothek mit dem Python-Image von Docker
Getestet mit Python
Python beginnt mit ()
mit Syntax (Python)
Verwenden Sie Application Insights mit Python 3 (einschließlich Flaschen).
Bingo mit Python
Zundokokiyoshi mit Python
Verwenden von C ++ - Funktionen aus Python mit pybind11
Verwenden Sie den Phantomjs-Webdriver von Selen mit Pythons Unittest
Bis Sie opencv mit Python verwenden können
Verwenden Sie Python und MeCab mit Azure-Funktionen
Excel mit Python
Mikrocomputer mit Python
Mit Python besetzen
Ich möchte MATLAB feval mit Python verwenden
Verwenden Sie zusätzliche Python-Pakete mit Serverless Framework (v1.x)
Geben Sie die ausführbare Python-Datei an, die mit virtualenv verwendet werden soll
Verwenden Sie vorerst Logger mit Python
Python> Mit Laufzeitargumenten ausführen> Import argparse verwenden
Verwenden Sie mit pyenv mehrere Versionen der Python-Umgebung
Wickeln Sie C mit Cython für Python ein
Der einfachste Weg, OpenCV mit Python zu verwenden
Verwenden Sie verschiedene Rabbimq-Funktionen mit Python Pika
Ich möchte Temporäres Verzeichnis mit Python2 verwenden
Wie man tkinter mit Python in Pyenv benutzt
Verwenden Sie Python in einer Anaconda-Umgebung mit VS-Code