| Title: Aggregate internet links with mlvpn | |
| Author: Solène | |
| Date: 28 March 2020 | |
| Tags: openbsd | |
| Description: | |
| In this article I'll explain how to aggregate internet access bandwidth | |
| using | |
| **mlvpn** software. I struggled a lot to set this up so I wanted to | |
| share a | |
| how-to. | |
| ## Pre-requisites | |
| **mlvpn** is meant to be used with DSL / fiber links, not wireless or | |
| 4G links | |
| with variable bandwidth or packet loss. | |
| **mlvpn** requires to be run on a server which will be the public | |
| internet | |
| access and on the client on which you want to aggregate the links, this | |
| is like | |
| doing multiples VPN to the same remote server with a VPN per link, and | |
| aggregate them. | |
| Multi-wan roundrobin / load balancer doesn't allow to stack bandwidth | |
| but | |
| doesn't require a remote server, depend on what you want to do, this | |
| may be | |
| enough and mlvpn may not be required. | |
| **mlvpn** should be OS agnostic between client / server but I only | |
| tried | |
| between two OpenBSD hosts, your setup may differ. | |
| ## Some network diagram | |
| Here is a simple network, the client has access to 2 ISP through two | |
| ethernet | |
| interfaces. | |
| em0 and em1 will have to be on different rdomains (it's a feature to | |
| separate | |
| routing tables). | |
| Let's say the public ip of the server is 1.2.3.4. | |
| [internet] | |
| ↑ | |
| | (public ip on em0) | |
| #-------------# | |
| | | | |
| | Server | | |
| | | | |
| #-------------# | |
| | | | |
| | | | |
| | | | |
| | | | |
| (internet) | | (internet) | |
| #-------------# #-------------# | |
| | | | | | |
| | ISP 1 | | ISP 2 | | |
| | | | | (you certainly don't control | |
| those) | |
| #-------------# #-------------# | |
| | | | |
| | | | |
| (dsl1 via em0)| | (dsl1 via em1) | |
| #-------------# | |
| | | | |
| | Client | | |
| | | | |
| #-------------# | |
| ## Network configuration | |
| As said previously, em0 and em1 must be on different rdomains, it can | |
| easily be | |
| done by adding `rdomain 1` and `rdomain 2` to the interfaces | |
| configuration. | |
| Example in **/etc/hostname.em0** | |
| rdomain 1 | |
| dhcp | |
| ## mlvpn installation | |
| On OpenBSD the installation is as easy as `pkg_add mlvpn` (should work | |
| starting | |
| from 6.7 because it required patching). | |
| ## mlvpn configuration | |
| Once the network configuration is done on the client, there are 3 steps | |
| to do | |
| to get aggregation working: | |
| 1. mlvpn configuration on the server | |
| 2. mlvpn configuration on the client | |
| 3. activating NAT on the client | |
| ### Server configuration | |
| On the server we will use the UDP ports 5080 et 5081. | |
| Connections speed must be defined in bytes to allow **mlvpn** to | |
| correctly | |
| balance the traffic over the links, this is really important. | |
| The line `bandwidth_upload = 1468006` is the maximum **download | |
| bandwidth of the | |
| client** on the specified link in bytes. If you have a download speed | |
| of 1.4 MB/s | |
| then you can choose a value of 1.4\*1024\*1024 => 1468006. | |
| The line `bandwidth_download = 102400` is the maximum **upload | |
| bandwidth of the | |
| client** on the specified link in bytes. If you have an upload speed of | |
| 100 kB/s | |
| then you can choose a value of 100*1024 => 102400. | |
| The **password** line must be a very long random string, it's a shared | |
| secret | |
| between the client and the server. | |
| # config you don't need to change | |
| [general] | |
| statuscommand = "/etc/mlvpn/mlvpn_updown.sh" | |
| protocol = "tcp" | |
| loglevel = 4 | |
| mode = "server" | |
| tuntap = "tun" | |
| interface_name = "tun0" | |
| cleartext_data = 0 | |
| ip4 = "10.44.43.2/30" | |
| ip4_gateway = "10.44.43.1" | |
| password = | |
| "apoziecxjvpoxkvpzeoirjdskpoezroizepzdlpojfoiezjrzanzaoinzoi" | |
| bindhost = "1.2.3.4" | |
| bindport = 5080 | |
| bandwidth_upload = 1468006 | |
| bandwidth_download = 102400 | |
| bindhost = "1.2.3.4" | |
| bindport = 5081 | |
| bandwidth_upload = 1468006 | |
| bandwidth_download = 102400 | |
| ### Client configuration | |
| The `password` value must match the one on the server, the values of | |
| `ip4` and | |
| `ip4_gateway` must be reversed compared to the server configuration | |
| (this is so | |
| in the following example). | |
| The `bindfib` lines must correspond to the according rdomain values of | |
| your | |
| interfaces. | |
| # config you don't need to change | |
| [general] | |
| statuscommand = "/etc/mlvpn/mlvpn_updown.sh" | |
| loglevel = 4 | |
| mode = "client" | |
| tuntap = "tun" | |
| interface_name = "tun0" | |
| ip4 = "10.44.43.1/30" | |
| ip4_gateway = "10.44.43.2" | |
| timeout = 30 | |
| cleartext_data = 0 | |
| "apoziecxjvpoxkvpzeoirjdskpoezroizepzdlpojfoiezjrzanzaoinzoi" | |
| remotehost = "1.2.3.4" | |
| remoteport = 5080 | |
| bindfib = 1 | |
| remotehost = "1.2.3.4" | |
| remoteport = 5081 | |
| bindfib = 2 | |
| ### NAT configuration (server side) | |
| As with every VPN you must enable packet forwarding and create a pf | |
| rule for | |
| the NAT. | |
| **Enable forwarding** | |
| Add this line in **/etc/sysctl.conf**: | |
| net.inet.ip.forwarding=1 | |
| You can enable it now with `sysctl net.inet.ip.forwarding=1` instead of | |
| waiting | |
| for a reboot. | |
| In pf.conf you must allow the UDP ports 5080 and 5081 on the public | |
| interface | |
| and enable nat, this can be done with the following lines in pf.conf | |
| but you | |
| should obviously adapt to your configuration. | |
| # allow NAT on VPN | |
| pass in on tun0 | |
| pass out quick on em0 from 10.44.43.0/30 to any nat-to em0 | |
| pass in on egress inet proto udp from any to (egress) port | |
| 5080:5081 | |
| ## Start mlvpn | |
| On both server and client you can run mlvpn with rcctl: | |
| rcctl enable mlvpn | |
| rcctl start mlvpn | |
| You should see a new tun0 device on both systems and being able to ping | |
| them | |
| through tun0. | |
| Now, on the client **you have to add a default gateway through the | |
| mlvpn | |
| tunnel** with the command ` route add -net default 10.44.43.2` (adapt | |
| if you | |
| use others addresses). I still didn't find how to automatize it | |
| properly. | |
| Your client should now use both WAN links and being visible with the | |
| remote | |
| server public IP address. | |
| **mlvpn** can be used for more links, you only need to add new | |
| sections. | |
| **mlvpn** also support IPv6 but I didn't take time to find how to make | |
| it work, | |
| si if you are comfortable with ipv6 it may be easy to set up IPv6 with | |
| the | |
| variables `ip6` and `ip6_gateway` in mlvpn.conf. |