Convert TUN/TAP to Socks5/HTTP proxy (OpenVPN as proxy)

These are very useful utilities — they convert TUN/TAP to Socks or HTTP Proxy, allowing to use VPN as a proxy (OpenVPN as Socks5), does not require root privileges.

tunsocks is a user-level SOCKS, HTTP, and port forwarding proxy for use with VPNs that typically interact with tun devices. Rather than passing bytes to and from the tun device, they can pass the data to and from this user-level program. tunsocks is implemented using lwIP.

Additionally, tunsocks provides connection sharing via NAT.

ocproxy is a user-level SOCKS and port forwarding proxy for OpenConnect based on lwIP. When using ocproxy, OpenConnect only handles network activity that the user specifically asks to proxy, so the VPN interface no longer “hijacks” all network traffic on the host.

@ValdikSS Thanks for suggestions. But due to a lack of documentation for tunsocks isn’t obvious how setup forwarding traffic from created socks5 to specific tun interface. Could you provide some examples of using tunsocks?

What I want to achieve is like this:

User (socks5 client) – [vps with socks5 server + several tun interfaces (openvpn clients connected to different vpn servers)] – several outputs to the internet via different vpn servers

E.g.
port 8081 socks5 - forward all client’s requests to tun1
port 8082 socks5 - forward all client’s requests to tun2
etc.

Sorry, I haven’t tried it personally.

For OpenVPN, there’s a patch for ocproxy support, but it’s outdated (for 2.3.x branch). I’ve ported it to the recent 2.5, but this is PoC (Windows not supported, yet).
You can use it with ocproxy or tunsocks, which expose VPN as a SOCKS/HTTP proxy.

FYI, there’s similar projects for WireGuard: wghttp, wg-http-proxy, wireproxy, onetun

If you already have tun interfaces (regular VPN) and you want to setup proxy on a server, you just need to bind outgoing requests of the proxy to specific tun interface, and also make sure that there’s default route over that interface with higher metric than the regular route.

ocproxy/tunsocks, on the other hand, allows you to “emulate” tun interface and “convert” it into proxy. There won’t be a real tun interface in the OS in this case.

Собрать tunsocks очень сложно. Я предлагаю менее элегантное, но более доступное решение на базе виртуалки. Достоинством является кроссплатформенность и то, что можно будет преобразовать в прокси любой VPN.

В главном окне VirtualBox: Файл - Настройки - Сеть - Виртуальные сети хоста - значок + (добавляете новую сеть) vboxnet0. Настройки vboxnet0 такие:
Адаптер:
IPv4 адрес: 192.168.56.1
IPv4 маска сети: 255.255.255.0
DHCP сервер:
Отключен

01

Устанавливаете Windows в виртуалку.
У виртуалки должно быть два сетевых адаптера.
Это уже настройки самой виртуалки, а не глобальные:
Адаптер 1. NAT, тут всё понятно, по умолчанию.
Адаптер 2. Тип подключения: Виртуальный адаптер хоста. Имя: vboxnet0 (которое мы создавали в глобальных настройках).

В реальной системе (в хосте) должен появиться адаптер vboxnet0. Если нет (например, в Linux), в Network Manager’е выберите “Добавить подключение - Ethernet”.
Его нужно настроить. Имя: VirtualBox.
Параметры IPv6: Игнорировать
Параметры IPv4: Вручную
Адрес: 192.168.56.1
Маска: 24 (указать надо 255.255.255.0, оно превратится в 24)
Шлюз: пустой (обязательно должен быть пустой, иначе пропадет интернет)
DNS: Любой, например 8.8.8.8
Вкладка Ethernet:
Устройство: vboxnet0

Запустите виртуальную Windows, установите гостевые дополнения.
Теперь настройка сети внутри виртуальной Windows:
1-ый адаптер (можно переименовать в NAT): Свойства - оставить только галочку на “Протокол Интернета (TCP/IP)” - Свойства - “Получить IP адрес автоматически”, DNS тоже автоматически или можно указать свой.

2-ый адаптер (можно переименовать в Internal): Свойства - оставить только галочку на “Протокол Интернета (TCP/IP)” - Свойства:
IP-адрес: 192.168.56.2
Маска подсети: 255.255.255.0
Основной шлюз: пустой (обязательно должен быть пустой, иначе пропадет интернет)
DNS сервера по желанию, например 192.168.56.1, 8.8.8.8 или пустой

Итак, мы создали виртуальную внутреннюю сеть между хостом (192.168.56.1) и виртуалкой (192.168.56.2). (Адаптер 2)
При этом виртуалка также получает интернет через NAT. (Адаптер 1)

Поднимаете в виртуальной Windows любой VPN.
А теперь надо установить в виртуальную Windows какой-нибудь локальный прокси, например, Proxomitron, который примет интернет от виртуального VPN и перешлет в хост с помощью прокси.
Proxomitron соответственно должен быть запущен вместе с виртуальным VPN.
Настройки Proxomitron такие:
В главном окне снимаете все галочки.

06

Config - Don’t use textures (отключает цветную тему, требуется перезапуск)
Access - Allow access to the following IP address range - From 192.168.56.1 to 192.168.56.2
Blockfile - удаляете все строчки
HTTP - локальный порт любой, например 8020, следите чтобы не было конфликтов
File - Save default settings

07

Теперь в реальной системе (в хосте) в браузерах вы можете указать HTTP и HTTPS прокси
192.168.56.2 порт 8020
И браузеры получат доступ к VPN через прокси.
Получится VPN > Proxy конвертер с помощью виртуалки.

Чтобы не было утечек (коннектов мимо прокси) браузеры нужно дополнительно настроить.
На примере Firefox отключить в about:config следующие опции:
media.peerconnection.enabled - false (WebRTC)
network.dns.disableIPv6 - true (IPv6)
network.notify.IPv6 - false (IPv6)
network.http.http3.enable - false (HTTP3/QUIC UDP) в хромобраузерах chrome://flags #enable-quic - Disabled
network.proxy.failover_direct - false (из-за проблем с прокси может быть fallback в direct)

Но, во всей этой системе нет Kill switch. Если виртуальный VPN отключится (во время реконнекта tun шлюз разорвется), то Proxomitron будет транслировать в прокси интернет, который виртуалка получает по NAT.
Так что забота о Kill switch перекладывается на виртуальный VPN. С OpenVPN наверняка будут проблемы. Wireguard держит шлюз надежнее.

Необязательно:
Можно сделать 100% рабочий Kill Switch. Но это ограничит протоколы VPN до TCP на 443 порту.
В виртуалке отключаем NAT адаптер (в VirtualBox снимаем галочку “кабель подключен” или можно отключить адаптер в самой виртуальной системе). Итак, виртуалка лишена интернета. Надо ей его провести. Проведем его все через тот же виртуальный сетевой интерфейс.
Для этого на реальной системе поднимаем другой локальный прокси. Это может быть тоже Proxomitron. В Linux хосте это может быть polipo. Вот его конфиг:

logSyslog = false
#logFile = polipo.log

proxyAddress = 192.168.56.1
proxyPort = 8060

allowedClients = 192.168.56.2, 192.168.56.1, 127.0.0.1
allowedPorts = 1-65535

proxyName = "direct"

cacheIsShared = false

#socksParentProxy = 127.0.0.1:9050
#socksProxyType = socks5
#parentProxy = 127.0.0.1:8080

chunkHighMark = 67108864

diskCacheRoot = ""
localDocumentRoot = ""

disableLocalInterface = true
disableConfiguration = true

dnsUseGethostbyname = yes

disableVia = true

censoredHeaders = from,accept-language,x-pad,link
censorReferer = maybe

maxConnectionAge = 10m
maxConnectionRequests = 120
serverMaxSlots = 16
serverSlots = 8
tunnelAllowedPorts = 1-65535

Теперь в виртуальном VPN мы должны указать этот вышестоящий HTTP прокси: 192.168.56.1:8060
Через прокси могут работать, например OpenVPN TCP и SoftEther.

Если у виртуального VPN будут проблемы и он разорвет шлюз, то в виртуалке интернета не будет (кроме вышестоящего прокси, но о нем знает только VPN клиент и будет через него реконнектится). А Proxomitron, который раздает нам VPN интернет в реальную систему, останется без интернета и будет ждать реконнекта VPN. Тем самый предотвращается утечка в случае сбоев.

Вообще, такой способ позволяет проводить хитрые манипуляции. Можно, например, пустить OpenVPN через любой прокси (если в polipo указать еще более вышестоящий). Но все прокси ограничены TCP.

У меня появилась возможность использовать SoftEther VPNGate в Linux, хотя SoftEther VPNGate не поддерживает Linux.

По поводу tunsocks поясните, пожалуйста. Я правильно понимаю, сначала я должен скомпилировать tunsocks https://github.com/russdill/tunsocks потом openvpn-tunpipe https://github.com/ValdikSS/openvpn-tunpipe потому что в оригинальном openvpn клиенте нет поддержки tunpipe/tunsocks? Или есть? Если нет, ValdikSS, как ты умудрился добавить поддержку tunpipe в openvpn (2.5) и следить за актуальностью openvpn в своем репозитории? Где эти патчи? Сейчас в твоем репозитории последний коммит от 16 июля 2022 года, что примерно соответствует 2.5.7. А если я соберу коммит от 2 мая 2021 (2.5.2) там будет поддержка tunpipe?

А запускать потом все это дело надо будет как-то так?
openvpn-tunpipe --script-tun --script “tunsocks -D 8080 -R ssh -L 8888:webproxy.example.com:80” vpn.example.com
Это пример со страницы tunsocks
Здесь тоже непонятно. Причем тут ssh и зачем два порта?
vpn.example.com можно ли заменить на путь к конфигу .ovpn или как потом скормить конфиг проге?

В общем, я полагаю openvpn (с поддержкой tunpipe) будет передавать управление tun’ом скрипту tunsocks (команды --script-tun --script)
Т.е. что-то вроде такого?
openvpn-tunpipe --script-tun --script “tunsocks -D 8080” config.ovpn
И будет локальный socks прокси 127.0.0.1:8080 с VPN интернетом?
Хотелось бы, чтобы прояснили финальную команду запуска.

Я скомпилировал tunsocks и openvpn-tunpipe. И как теперь их подружить?
Ничего не выходит. Пробовал даже такое:
sudo openvpn-tunpipe config.ovpn | tunsocks -D 8010
А за время тестов меня забанил Proton.
Ничего не понятно из документации. Почти нет примеров.

Для оригинально патча работало так:

./openvpn-tunpipe --config config.ovpn --script-security 2 --dev '|./tunsocks -D 127.0.0.1:8010 -d 8.8.8.8'

sudo не нужен, адрес слушающего прокси лучше указать явно (127.0.0.1 или другой), localhost через hosts файл может оказаться не тем, что нужно, не забыть про днс.

Ошибка после openvpn соединения:
Error: problem with tun vs. tap setting
Exiting due to fatal error

Но у меня старая система и tunsocks новее Mar 1, 2017 не собирается.

А openvpn я пробовал 3 версии и со всеми та же ошибка.
https://github.com/ValdikSS/openvpn-tunpipe/commit/bf90fcd141996c7f6ca10f74ebebf1160f8db5fc
последняя версия Jul 16, 2022 (официальный openvpn был в это время версии 2.5.7)

https://github.com/ValdikSS/openvpn-tunpipe/commit/c2912912047fdd228faedb6466672288e14dbba6
May 2, 2021 (официальный openvpn был в это время версии 2.5.2)

https://github.com/OpenVPN/openvpn/releases/tag/v2.3.18
Sep 25, 2017 (непатченный?)

Параметры сборки openvpn (последней версии от valdikss) такие, в общем всё включено, кроме systemd и selinux:

./configure --prefix=/opt/tunsocks --enable-silent-rules --enable-static --enable-shared --disable-debug --disable-systemd --disable-selinux --enable-lzo --enable-lz4 --enable-ofb-cfb --enable-plugins --enable-management --enable-pkcs11 --enable-fragment --enable-port-share --enable-iproute2 --enable-plugin-auth-pam --enable-pam-dlopen --disable-unit-tests --with-crypto-library=openssl

Как пропатчить 2.3.18 хотя бы?

В конфиге для протона нет опции dev-type, возможно добавление исправит, или так:

./openvpn-tunpipe --config config.ovpn --script-security 2 --dev '|./tunsocks -D 127.0.0.1:8010 -d 8.8.8.8' --dev-type tun

Но этой ошибки в патченной версии быть не должно

Ничего не помогает (и я пробовал не только Proton). Я даже скомпилировал 2.3.3 с форумными патчами. Чего мне стоило вытащить эти патчи из текста, не буду говорить. tunsocks заменил на ocproxy (он 2014 года) и все равно ошибки.
Т.е. даже старая патченная версия не работает у меня.

Интересно, но должно работать.
Покажите полностью строчку которой запускаете?
Может ковычки одинарные так срабатывают?
Может при копировании уникод внедрился
Двойные меняют ошибку?

--dev "|./tunsocks -D 127.0.0.1:8010"

Заработало.

Пересобрал openvpn. На этот раз решил не городить опций в configure (т.е. положился на дефолты) и еще посмотрел как openvpn собирается в Arch и Ubuntu. Сравнил (openvpn --version) системный openvpn и собранный рабочий. Оказалось, что в системном enable-iproute2=yes, а в моем собранном от valdikss enable-iproute2=no. Причем, ни системные (ubuntu ppa, ubuntu repo, arch), ни я не указывали enable-iproute2 в configure. Значит в исходниках оригинального openvpn iproute2 по умолчанию включен, а в исходниках от valdikss по умолчанию отключен. Я же раньше явно включал iproute2.

Привожу инструкции как я всё собирал.

sudo apt install checkinstall autoconf git
sudo apt build-dep openvpn

git clone https://github.com/russdill/tunsocks
cd tunsocks
git checkout 2a85b5ffda7adfeabaa2369a02acbfc4e085b30d
git submodule update --init
git checkout 2a85b5ffda7adfeabaa2369a02acbfc4e085b30d
autoreconf -fi
./configure --prefix=/usr --enable-silent-rules --enable-pcap
make
sudo checkinstall --install=no

Версия tunsocks от 1 марта 2017 года
Можно собрать версию новее, тогда git checkout указывать не нужно, но будет клонироваться и использоваться больше субмодулей (lwip проекта) и на старых системах может не собраться. lwip клонируется каким-то хитрым способом и на некоторых провайдерах могут быть сбои при клонировании.
Результатом сборки будет один файл /usr/bin/tunsocks
Хотя и указано checkinstall --install=no, checkinstall не только создает deb пакет, но и копирует собранные файлы в системные пути (без регистрации в пакетом менеджере), имейте в виду.
Когда checkinstall спросит создавать ли доки, откажитесь (меньше мусора будет).

git clone --depth 1 https://github.com/ValdikSS/openvpn-tunpipe --branch tun_pipe --single-branch
cd openvpn-tunpipe
autoreconf -fi
./configure --help
./configure --prefix=/usr --sbindir=/sbin --includedir=/usr/include/openvpn-tunpipe --mandir=/usr/share/man/openvpn-tunpipe --docdir=/usr/share/doc/openvpn-tunpipe --libdir=/usr/lib/openvpn-tunpipe --enable-pkcs11 --enable-x509-alt-username --enable-plugins --disable-systemd --disable-unit-tests
make
sudo checkinstall --install=no

Эти параметры взяты из Ubuntu и Arch. Я думаю, самое главное --disable-iproute2 но это по умолчанию в исходниках от valdikss, поэтому я не указывал явно.
Пути изменены, чтобы не затереть системный openvpn.
include, доки и маны потом можно удалить. lib оставить.
Нужно потом переименовать /sbin/openvpn в /sbin/openvpn2, т.к. они оба в PATH.

Вот куда срет openvpn установка:
/sbin/openvpn
/usr/lib/openvpn-tunpipe

можно удалить:
/usr/include/openvpn-tunpipe
/usr/share/man/openvpn-tunpipe
/usr/share/doc/openvpn-tunpipe

Запуск:
openvpn2 --config 'config.ovpn' --script-security 2 --dev '|tunsocks -D 127.0.0.1:8010 -d 1.1.1.1'

И хотя это вряд ли кому-нибудь будет нужно, вот готовые пакеты для Ubuntu 16.04 i386. Извините, зависимости в deb пакеты не прописывал. Проверить их можно readelf -d или ldd.
tunsocks-01.03.2017-xenial-i386.deb (40.6 КБ)
openvpn-tunpipe-2.6-xenial-i386.deb (340.8 КБ)

А если в Msys (ex Cygwin) собрать? Он вроде эмулирует POSIX. Правда, не будет поддержки XP и библиотеку msys-2.0.dll придется тащить с собой. tunsocks, кстати тоже не хочет кросскомпилиться в mingw.
В Msys как-то собирал вещи, которые не компилились в mingw. Хотя, рекомендуют именно mingw.