
Some of us cannot use the internet without a VPN for various reasons: some need a dedicated IP, and it's simpler and cheaper to buy a VPS with two IPs than to purchase an address from the provider; others want access to all websites, not just those permitted within the Russian Federation; and some need IPv6, which their provider does not offer…
Most often, a VPN connection is set up on the device being used at that moment, which is quite justified if you only have one computer and one phone that you rarely use simultaneously. However, if your home network has multiple devices or if there are devices on which you cannot configure a VPN, it would be more convenient to establish the tunnel directly on the home router, eliminating the need to configure each device individually.
If you've ever installed OpenVPN on your router, you were likely unpleasantly surprised by its speed. The SoCs of even inexpensive routers can handle nearly gigabit traffic effortlessly by offloading routing and NAT functions to a separate chip designed solely for this purpose, while the main processors of such routers are quite weak since they hardly face any load. This compromise allows for high-speed performance and significantly lowers the price of the finished device—routers with powerful processors cost several times more and are positioned not only as internet-sharing devices but also as NAS, torrent downloaders, and home multimedia systems.
My router, the TP-Link TL-WDR4300, can't be considered new—it was released in mid-2012 and has a 560 MHz MIPS32 74Kc processor, whose power is only sufficient for 20-23 Mbps of encrypted traffic through OpenVPN, which is quite limited by today's home internet speed standards.
How can we increase the speed of the encrypted tunnel? My router is quite functional, supports 3×3 MIMO, and generally works well; I'd prefer not to change it.
Given that it is now common to create 10-megabyte web pages, write desktop applications in node.js, and package them into 100-megabyte files while increasing computational power instead of optimizing, we will do something dreadful—we'll shift the VPN connection onto the powerful single-board computer Orange Pi One, which we'll install in the router case, without occupying existing network and USB ports, all for $9.99*!
* + shipping, + taxes, + for beer, + MicroSD.
OpenVPN
One cannot call the router's processor entirely weak—it can encrypt and hash data using the AES-128-CBC-SHA1 algorithm at a speed of 50 Mb/s, which is significantly faster than how OpenVPN operates, and the modern stream cipher CHACHA20 with the POLY1305 hash can achieve 130 megabits per second! So why is the VPN tunnel speed so low? The issue lies in the context switching between user space and kernel space: OpenVPN encrypts traffic and communicates with the outside world in user context, while the routing occurs in kernel context. The operating system has to constantly switch back and forth for each received or transmitted packet, and this operation is not fast. This problem is inherent to all VPN applications that work through the TUN/TAP driver, and it cannot be said that the low-speed issue is due to poor optimization of OpenVPN (although, of course, there are parts that could be reworked). No userspace VPN client delivers even a gigabit with encryption turned off on my laptop, let alone systems with a weak processor.
Orange Pi One
The Orange Pi One single-board computer from Xunlong offers the best performance-to-price ratio available right now. For $9.99*, you get a solid quad-core ARM Cortex-A7 processor operating at a steady 1008 MHz, which clearly outperforms its competitors in the price category, such as the Raspberry Pi Zero and Next Thing C.H.I.P. However, that's where the advantages end. Xunlong pays zero attention to the software for its boards and at the time of launching the One for sale, it didn't even provide a configuration file for the board, let alone ready-made images. Allwinner, the SoC manufacturer, also does not show much care for supporting its product. Their only concern is minimal functionality in Android 4.4.4, which means we are forced to use kernel version 3.4 with Android patches. Fortunately, there are enthusiasts who compile distributions, modify the kernel, and write code for supporting the boards in the mainline kernel, essentially doing the manufacturer's work to make this subpar product function acceptably. For my purposes, I chose the Armbian distribution, as it is frequently and conveniently updated (new kernels can be installed directly through the package manager, rather than by copying files to a special partition, as is usually done with Allwinner), and it also supports most peripherals, unlike others.
Router
To prevent the weak router processor from being overloaded with encryption and to speed up our VPN connection, we can shift this task to the more powerful Orange Pi processor by connecting it to the router in some way. I think of connecting via either Ethernet or USB — both standards are supported by both devices, but I wouldn't want to occupy existing ports. Fortunately, there is a solution.
The GL850G USB hub chip used in the router supports four USB ports, two of which are not soldered. It is unclear why the manufacturer chose not to solder them, but I assume it's to prevent users from connecting four high-power devices (such as hard drives) at once, since the stock power supply of the router is not designed for that load. In any case, this works to our advantage.

To obtain another USB port, it is enough to solder two wires to pins 8(D-) and 9(D+) or 11(D-) and 12(D+).

However, it is not enough to simply connect two USB devices and hope that everything will work seamlessly as it would with Ethernet. First, we need to make one of them operate in USB Client mode rather than USB Host mode; second, we need to determine how the devices will recognize each other. There are many drivers for so-called USB Gadgets (named after the Linux kernel subsystem) that allow emulation of various types of USB devices: network adapters, audio cards, keyboards and mice, flash drives, cameras, and consoles via serial ports. Since our device will operate on a network, the emulation of an Ethernet adapter is the most suitable option.
There are three standards for Ethernet-over-USB:
- Remote NDIS (RNDIS). An outdated standard from Microsoft, predominantly used back when Windows XP was in vogue.
- Ethernet Control Model (ECM). A simple standard that encapsulates Ethernet frames within USB packets. It is well-suited for wired modems with USB connections, where it is convenient to transmit frames without processing, but due to its simplicity and USB bus limitations, it does not operate very quickly.
- Ethernet Emulation Model (EEM). A more sophisticated protocol that takes into account USB limitations and optimally aggregates multiple frames into one, thereby enhancing throughput.
- Network Control Model (NCM). The latest protocol. It carries the advantages of EEM and further optimizes bus operations.
To get any of these protocols working on our board, as always, we will encounter some difficulties. Because Allwinner is only interested in the Android parts of the kernel, only the Android Gadget works properly — the code that implements connection via adb, device export using the MTP protocol, and flash drive emulation on Android devices. The Android Gadget itself supports the RNDIS protocol, but in the Allwinner kernel, it is broken. If you try to compile the kernel with any other USB Gadget, the device simply won’t show up in the system, no matter what you do.
To solve the problem, ideally, you would need to find the initialization point of the USB controller in the modified developers' code of the Android gadget android.c, but there is also a workaround to get at least Ethernet emulation over USB working:
--- sun8i/drivers/usb/sunxi_usb/udc/sunxi_udc.c 2016-04-16 15:01:40.427088792 +0300
+++ sun8i/drivers/usb/sunxi_usb/udc/sunxi_udc.c 2016-04-16 15:01:45.339088792 +0300
@@ -57,7 +57,7 @@
static sunxi_udc_io_t g_sunxi_udc_io;
static u32 usb_connect = 0;
static u32 is_controller_alive = 0;
-static u8 is_udc_enable = 0; /* is udc enable by gadget? */
+static u8 is_udc_enable = 1; /* is udc enable by gadget? */
#ifdef CONFIG_USB_SUNXI_USB0_OTG
static struct platform_device *g_udc_pdev = NULL;This patch forcibly enables USB client mode, allowing the use of standard USB Gadgets from Linux.
Now you need to rebuild the kernel with this patch and the required gadget. I chose EEM since it proved to be more efficient than NCM based on testing results.
The Armbian team provides for all supported boards in the distribution. Just download it, place our patch in userpatches/kernel/sun8i-default/otg.patch, edit compile.sh and select the required gadget:

The kernel will compile into a deb package, which can be easily installed on the board via dpkg.
You only need to connect the board via USB and configure our new network adapter to obtain an address via DHCP. To do this, you should add something like the following to /etc/network/interfaces:
auto usb0
iface usb0 inet dhcp
hwaddress ether c2:46:98:49:3e:9d
pre-up /bin/sh -c 'echo 2 > /sys/bus/platform/devices/sunxi_usb_udc/otg_role'It's better to set the MAC address manually, as it will be random with each device reboot, which is inconvenient and cumbersome.
Connect the MicroUSB cable to the OTG port, then power it from the router (you can apply power to pins 2 and 3 on the header, not just to the power connector).
Now, configure the router. Just install the package with the EEM driver and add our new USB network device to the bridge of the local firewall zone:
opkg install kmod-usb-net-cdc-eem
To route all traffic through the VPN tunnel, you either need to add a SNAT rule for the board's IP address on the router side or provide the board's IP address as the gateway address via dnsmasq. The latter is done by adding the following line to /etc/dnsmasq.conf:
dhcp-option = tag:lan, option:router, 192.168.1.100where 192.168.1.100 — the IP address of your board. Don't forget to set the router address in the network settings on the board itself!
A melamine sponge was used to isolate the board's contacts from the router's contacts. It turned out something like this:

Conclusion
The network operates surprisingly quickly through USB: 100-120 Mbps; I expected less. OpenVPN allows about 70 Mbps of encrypted traffic, which isn't a lot, but it's sufficient for my needs. The router cover does not close tightly, leaving a small gap. Aesthetes can desolder the Ethernet and USB Host connectors from the board, which would allow the cover to close completely, and there would still be some space left.
Or better yet, don't engage in such nonsense and just buy .
Source: habr.com
