Use TUN / TAP with Python

Overview

A story about operating TUN / TAP, a virtual network driver used in VPN implementation, from Python. What I checked when I created https://github.com/kstm-su/dnsvpn.

Prerequisites

--Mac or Linux (Windows not verified) --Python (verified with 3.5)

About TUN / TAP

From Wikipedia

TAP simulates an Ethernet device and manipulates the data link layer. TUN simulates the network layer and manipulates IP packets and the like. TAP is used for bridge generation and TUN is used for routing.

Packets sent by the OS to a TUN / TAP device are sent to the user program connected to that device. You can also send packets from your program to the TUN / TAP device. In that case, the TUN / TAP device passes those packets to the OS protocol stack, so it looks as if the packets were received from the outside from the OS side.

If you want to handle from L3 or higher, use TUN, and if you want to handle from L2, use TAP.

TUN / TAP installation

Mac Can be installed with brew.

$ brew cask install tuntap

It is OK if there are tun [0-15] and tap [0-15] under / dev.

Linux If the kernel is 2.2.x, 2.4.x or later, it should be included as standard

$ lsmod | grep tun

If nothing comes out, do modprobe

$ sudo modprobe tun

All you need is / dev / net / tun.

Register a TUN / TAP device

Make TUN / TAP visible with ʻip link. Basically, you just open the device file with ʻopen, but in the case of Linux, you need to set the device name and flag with ʻioctl`, which is a little troublesome. When the program ends, the device is unregistered, so the sample program does not end in an infinite loop.

Mac Just open / dev / tun * and it's easy. (/ Dev / tap * when using TAP)

# tuntap-darwin.py
import os
import time
tun = os.open('/dev/tun0', os.O_RDWR)
while True:
    time.sleep(1)

When you run it, you can see that the device file name is recognized as the network device name as it is.

$ sudo python tuntap-darwin.py &
$ ip link show tun0
tun0: flags=8850<POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	open (pid 2251)

Linux Open / dev / net / tun and use ʻioctlto set the device name such as TUN or TAP. When using TAP, setTUN_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)

When you run it, you can see that it recognizes the string passed to the argument name of ʻifreq` as the network device name.

$ sudo python tuntap-linux.py &
$ ip addr show hoge
6: hoge: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 500
    link/none

Communicate with TUN / TAP

Try sending and receiving data using the registered TUN / TAP device. On both Mac and Linux, just receive with read and send with write. However, if you do read or write as it is, you will get angry, so execute an external command to link up.

# 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)

Try to ping the network device you created

$ 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'

Looking at Wireshark, two are displayed for each ping. This is because the received packet is sent as it is. スクリーンショット 2016-12-03 4.32.29.png

Recommended Posts

Use TUN / TAP with Python
[Python] Use JSON with Python
Use mecab with Python3
Use DynamoDB with Python
Use Python 3.8 with Anaconda
Use python with docker
Use Trello API with python
Use Twitter API with Python
Use subsonic API with python3
Python: How to use async with
Use PointGrey camera with Python (PyCapture2)
Use vl53l0x with Raspberry Pi (python)
[Python] Use Basic/Digest authentication with Flask
Use NAIF SPICE TOOLKIT with Python
Use rospy with virtualenv in Python3
Use Python in pyenv with NeoVim
How to use FTP with Python
Use Windows 10 speech synthesis with Python
Use OpenCV with Python 3 in Window
Use PostgreSQL with Lambda (Python + psycopg2)
FizzBuzz with Python3
Scraping with Python
Statistics with python
Use smbus with python3 under pyenv environment
Use DeepL with python (for dissertation translation)
Scraping with Python
Python with Go
Use Amazon Simple Notification Service with Python
Twilio with Python
Integrate with Python
[Python] Use string data with scikit-learn SVM
Play with 2016-Python
[Introduction to Python] Let's use foreach with Python
Use PIL and Pillow with Cygwin Python
AES256 with python
Use cryptography library cryptography with Docker Python image
Tested with Python
python starts with ()
with syntax (Python)
Use Application Insights with Python 3 (including bottles)
Bingo with python
Zundokokiyoshi with python
Use C ++ functions from python with pybind11
Use selenium phantomjs webdriver with python unittest
Until you can use opencv with python
Use Python and MeCab with Azure Functions
Excel with Python
Microcomputer with Python
Cast with python
I want to use MATLAB feval with python
Use additional Python packages with Serverless Framework (v1.x)
Specify the Python executable to use with virtualenv
Use logger with Python for the time being
Python> Run with run-time arguments> Use import argparse
Use multiple versions of python environment with pyenv
Wrap C with Cython for use from Python
The easiest way to use OpenCV with python
Use various rabbimq features with pika in python
I want to use Temporary Directory with Python2
How to use tkinter with python in pyenv
Use Python in Anaconda environment with VS Code