256-bit AES - the same standard that protects banking transactions

0%
· 9 min read

VPN on MikroTik: VLESS in a RouterOS 7 Container — Full Guide

In short: on MikroTik with RouterOS 7 there is one working path — the VLESS protocol via the Container feature. The router runs a lightweight container with xray; you need a model on ARM/ARM64/x86 and room for the image. It gives you traffic masquerading as ordinary HTTPS and stability on any network, and it supports XHTTP configurations too. The WireGuard built into RouterOS will not do for our service, and the section below explains why — read it first if you were counting on a 15-minute setup.

New to routers? An honest heads-up

MikroTik is a network engineer’s tool: there are no setup wizards here, and the logic of RouterOS assumes you understand routing. If you are picking your first VPN router for home, look at the Keenetic guide or TP-Link first: there everything is configured with buttons in a web interface. If MikroTik is already in place and you are comfortable with it — let’s go. Get stuck and Tainet support will help you work through your own configuration.

What you’ll need

  • A recent stable RouterOS 7 branch and the container package from Extra packages built for that same version. The version matters: on older builds /container/envs/add only accepts name= instead of list=, and the commands below answer expected end of command.
  • A model on ARM, ARM64 or x86 (hAP ax2/ax3, RB5009, CCR2004 and newer, x86/CHR) and room for the image — a USB stick, an NVMe or a free partition. /system/resource/print shows your architecture in architecture-name. mmips and smips boards (hEX, hEX S, hAP lite) have no container support at all; the hEX Refresh has it but only accepts arm32v5 images. If your model does not fit, the question is wider than one brand — how to tell whether your router will do is covered in the general overview.
  • A VLESS key from a service. With Tainet it lives in the Telegram bot or on this site in your personal account; the first 7 days are free, enough to get the setup running. In your account the MikroTik commands are assembled ready, with your key’s values already filled in — you just paste them into the terminal.

The practical steps are below; if you'd rather skip the setup, Tainet connects in a couple of minutes - through the Telegram bot or in your account on this site.

Why the built-in WireGuard will not do

RouterOS 7 has WireGuard natively, and it will even accept the configuration file. But what we hand out is not plain WireGuard — it is AmneziaWG: the same protocol plus the Jc, Jmin, Jmax, S1, S2 and H1H4 lines in the [Interface] section. They change how the traffic looks, and that is what keeps the connection alive on Russian networks, where plain WireGuard is unstable.

RouterOS does not know those lines and silently skips them. The client then greets the server in a way the server is not expecting — and no handshake happens at all. Three signs tell this apart from “it just does not work”:

  • the interface in /interface/wireguard/print shows running — it always does, which on its own means nothing;
  • the peer’s last-handshake field stays empty;
  • the rx counter sits at zero while tx grows — the router keeps sending, nothing comes back.

So there is nothing to “try for five minutes” here: it will not start working on any model or any firmware version. RouterOS has no official support for AmneziaWG parameters, and MikroTik has none planned.

There is one working path, and it is below.

Setup: VLESS through a container

The idea: the router runs a container that holds the VLESS connection, and RouterOS steers traffic into it. The image carries two components — xray itself and hev-socks5-tunnel; the second one is mandatory, because the router hands the container IP packets while xray speaks SOCKS. A bare xray image, multi-architecture or not, will not act as a gateway.

The image below is wiktorbgu/vless-hev-socks5-tunnel-mikrotik, built for amd64, arm64 and 32-bit ARM. It is third-party: neither ours nor MikroTik’s. The mikro tag is a build without geoip.dat/geosite.dat, for boards where memory is shared with the system.

The order of work is five steps, each spelled out below:

  1. Enable container support and confirm the change on the device itself.
  2. Bring up the container network: veth, bridge, address and NAT.
  3. Pass the nine parameters of your key to the container.
  4. Pull the image and start the container.
  5. Steer the devices you want into the tunnel with a mangle rule.

Step 1. Enable container support. Install the container package (Extra packages for your version), then:

/system/device-mode/update container=yes

RouterOS will ask you to confirm the change physically — by pressing the Reset button, or, on x86 and CHR, with a cold reboot, meaning powering the machine off and on. That is MikroTik’s safeguard; without it containers will not start. Container mode is switched back off the same way.

Step 2. Networking for the container.

/interface/veth/add name=veth-vless address=172.17.0.2/24 gateway=172.17.0.1
/interface/bridge/add name=containers
/interface/bridge/port/add bridge=containers interface=veth-vless
/ip/address/add address=172.17.0.1/24 interface=containers
/ip/firewall/nat/add chain=srcnat src-address=172.17.0.0/24 action=masquerade

Step 3. Pass your key’s parameters to the container. The values come from the vless:// link: address and port from its start, the rest from the parameters after ?. In your personal account these nine lines are assembled ready, with the values already filled in; the Tainet bot holds the link itself.

/container/envs/add list=vless key=REMOTE_ADDRESS value=SERVER_ADDRESS
/container/envs/add list=vless key=REMOTE_PORT    value=443
/container/envs/add list=vless key=ID             value=YOUR_UUID
/container/envs/add list=vless key=ENCRYPTION     value=none
/container/envs/add list=vless key=FLOW           value=xtls-rprx-vision
/container/envs/add list=vless key=FINGER_PRINT   value=FP_VALUE
/container/envs/add list=vless key=SERVER_NAME    value=SERVER_ADDRESS
/container/envs/add list=vless key=PUBLIC_KEY     value=PBK_VALUE
/container/envs/add list=vless key=SHORT_ID       value=SID_VALUE

Fill in FINGER_PRINT, PUBLIC_KEY and SHORT_ID with your own values — from the link or from the ready-made set in your account. The service does not hand out an arbitrary fingerprint: picking a “popular” one by hand gives you the one our own backend treats as conspicuous.

The parameter is list=, exactly. Some guides — and the image’s own description — use name=; that is the old syntax, and current RouterOS answers it with expected end of command.

Step 4. Create and start the container (root-dir goes on your storage):

/container/config/set registry-url=https://registry-1.docker.io tmpdir=disk1/tmp
/container/add remote-image=wiktorbgu/vless-hev-socks5-tunnel-mikrotik:mikro \
  interface=veth-vless root-dir=disk1/containers/vless envlist=vless \
  dns=1.1.1.1,8.8.8.8 start-on-boot=yes logging=yes name=vless
/container/start vless

Two lines here are not obvious and each costs you a silent failure. registry-url is set explicitly because RouterOS defaults to lscr.io while the image lives on Docker Hub. dns= is set explicitly because without DNS the container will not start at all.

Step 5. Steer the traffic. The simplest option is all traffic through the container with a separate routing table:

/routing/table/add name=to_vpn fib
/ip/route/add dst-address=0.0.0.0/0 gateway=172.17.0.2 routing-table=to_vpn
/ip/firewall/mangle/add chain=prerouting src-address=192.168.88.0/24 \
  dst-address=!192.168.88.0/24 \
  action=mark-routing new-routing-mark=to_vpn passthrough=yes

(Substitute your own local subnet; for selective routing change the condition in mangle — by device address or by destination lists. The dst-address=! exclusion is mandatory: without it traffic between your own subnets and VLANs ends up in the tunnel too. The separate routing table is not decoration either — a default route through the container in the main table would swallow the connection to the server itself, and the tunnel would loop back on itself.)

To check: /container/print — status running; the container log will show the connection established; devices from the marked subnet go out with the server’s IP. Check DNS, games and calls separately: with the xtls-rprx-vision flow UDP through the tunnel is not guaranteed, so DNS on the router is safer set statically in /ip/dns.

A note on configuration types: inside the container sits full xray, so it understands both VLESS and the XHTTP variants from a Tainet subscription — nothing needs filtering. That is what sets the MikroTik path apart from router solutions built on sing-box (like HomeProxy on OpenWRT), where XHTTP is not supported yet — the details are in the OpenWRT guide.

Tainet works with either path: a WireGuard config for the stock client, a VLESS subscription for OpenWRT — one subscription, both formats, plus the same servers on your phone and your computer. Sign up through the Telegram bot or in your account on this site, from $0.10 a day.

Try it →

Troubleshooting

The container won’t start. Four classic causes: device-mode is not confirmed (repeat step 1 and confirm with the button or a cold reboot), DNS is not set (dns= in /container/add, or entries in /ip/dns), there is not enough space (check the storage and root-dir), or the architecture (/system/resource/print → architecture-name; our image will not run on arm32v5).

The container runs but no traffic flows. Check the NAT rule for 172.17.0.0/24, the route in the routing table and the mangle rule — the three places where a packet usually gets lost. And compare the nine environment variables against your key: an empty or truncated PUBLIC_KEY is accepted silently, the container starts, and there is no connection.

Speed is lower than expected. Encryption inside the container loads the CPU: on the hAP ax series expect tens up to a hundred Mbps realistically; for gigabit workloads look at RB5009/CCR. If you need gigabit across the house, send only the devices that actually need the tunnel through it — that is exactly what the mangle rule is for.

Everything disappeared after a RouterOS upgrade. Check that the container package is installed for the new version, and restart the container.

Still not solved — write to support: we will advise for your specific model and configuration.

Frequently asked questions

Which MikroTik models are suitable for a VLESS container?

Any on ARM/ARM64/x86 with room for the image: hAP ax2/ax3, RB5009, CCR2004 and newer, the virtual CHR. mmips and smips boards (hEX, hEX S, hAP lite) have no container support at all. The hEX Refresh has it, but only accepts arm32v5 images, and this image has no build for that.

Why can’t I just use the built-in WireGuard?

Because it will not connect: our config carries masquerading parameters, RouterOS does not read them, and no handshake with the server happens. That is covered in detail above, together with the signs that make the failure visible on the router. How the masquerading works in VLESS — in the protocol breakdown.

Can I route only some of my devices through the VPN?

Yes, and that is MikroTik’s strong suit: change the conditions in the mangle rule — by device address, address-list or destination. The TV through the tunnel, the work laptop directly — that’s a routine task.

One subscription for the router and the phone — is that allowed?

Yes: a Tainet subscription is multi-device — the container on the router and Happ on your phone work off the same link. An overview of every platform is in the guide to devices.

If you want a service that gets along with MikroTik: in your Tainet account the container commands are assembled ready, with your key’s values already filled in — you just paste them into the router terminal. A free first week to try it out, from $0.10/day. Sign up in the Telegram bot or on this site in your personal account. Questions about your own setup — support is answered by real people.