Subject: socat: TUN option reduces throughput to almost nothing
Package: socat
Version: 1.7.3.1-2+deb9u1
Severity: normal
Using a TUN device with socat reduces throughput from almost-Gbit to
~100Kbit.
Testing was done using iperf, throughput went from ~950 Mbits/sec with
TCP4 option to ~120 Kbits/sec with TUN. See detailed output below. To
check whether it is actually a problem with socat specifically, I used
tun2socks[1], which gives much higher troughput using a TUN device.
There I've used ssh for quickly creating a socks tunnel. With tun2socks,
throughput was at ~450 Mbits/sec.
If it's helpful, I can assemble a set of reproducing commands using
socat that match the setup of tun2socks. Using socat with TUN and SOCKS
instead of the example TUN and TCP4 suffers from the same heavy
throughput impairment, as do several other more complicated setups with
socat whenever there's a TUN device involved somewhere.
To reproduce, use two machines running debian connected to the same Gbit
switch, and the commands listed below.
You might want to run some of the commands in screen sessions
(blocking).
I was able to reproduce the results with two ubuntu 18.10 machines using
socat version 1.7.3.2, so I assume the problems aren't fixed in testing.
Thank you.
## using TUN device
On the server machine (assuming address 192.168.1.2):
socat TUN:10.10.0.2/16,iff-up
TCP4-LISTEN:54321,bind=192.168.1.2,fork
iperf -s -p 15001 -B 10.10.0.2
On the client machine:
socat TUN:10.10.0.1/16,iff-up TCP4:192.168.1.2:54321
iperf -c 10.10.0.2 -p 15001 -t 30
example iperf output:
------------------------------------------------------------
Client connecting to 10.10.0.2, TCP port 15001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[ 3] local 10.10.0.1 port 35658 connected with 10.10.0.2 port 15001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-39.7 sec 640 KBytes 132 Kbits/sec
## using TCP4 for comparison
On the server machine:
socat TCP4-LISTEN:12345,bind=192.168.1.2,fork TCP4:127.0.0.1:15001
iperf -s -p 15001 -B 127.0.0.1
On the client machine:
socat TCP4-LISTEN:54321,bind=127.0.0.1,fork TCP4:192.168.1.2:12345
iperf -c 127.0.0.1 -p 54321 -t 30
example iperf output:
------------------------------------------------------------
Client connecting to 127.0.0.1, TCP port 54321
TCP window size: 2.50 MByte (default)
------------------------------------------------------------
[ 3] local 127.0.0.1 port 38984 connected with 127.0.0.1 port 54321
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-30.0 sec 3.30 GBytes 944 Mbits/sec
## tun2socks setup for comparison
On the server machine:
# setup dummy device
modprobe dummy
ip link add dummy0 type dummy
ip link set name tun2 dev dummy0
ifconfig tun2 10.10.0.2/16 up
# run test
iperf -s -p 54321 -B 127.0.0.1
socat TCP4-LISTEN:12345,bind=10.10.0.2,fork TCP4:127.0.0.1:54321
/usr/sbin/sshd -4Df /root/testconf -p 2222
On the client machine:
# setup tun device
ip tuntap add dev tun0 mode tun
ifconfig tun0 10.10.0.1/16
# run test
ssh -4ND 127.0.0.1:11111 -p 2222 root@192.168.1.2
tun2socks --logger stdout --tundev tun0 --netif-ipaddr 10.10.0.2
--netif-netmask 255.255.0.0 --socks-server-add$
Custom sshd test config (file /root/testconf in server config above):
----snip----
PermitRootLogin yes
StrictModes yes
ListenAddress 192.168.1.2
IgnoreRhosts yes
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
PasswordAuthentication yes
UsePAM no
UseDNS no
X11Forwarding no
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
PermitTunnel yes
AllowTcpForwarding yes
----snap----
example iperf output:
------------------------------------------------------------
Client connecting to 10.10.0.2, TCP port 12345
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[ 3] local 10.10.0.1 port 58456 connected with 10.10.0.2 port 12345
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-30.0 sec 1.49 GBytes 426 Mbits/sec
[1] https://github.com/ambrop72/badvpn/wiki/Tun2socks