Updated Saturday 2nd August 2025
This was originally going to be a post about how to configure a dedicated interface for management traffic on Proxmox VE but alas, after many hours of trying to get HTTPS traffic over on the MGMT VRF, I decided to try a different solution. However, I did manage to get SSH traffic to use the OOBM Interface so I though I’ll document that for future use.
All credit goes to Phil and the people who commented on his post. I’m only writing this post because I think this information should be stored on more than one place on the Internet.
Source: https://interpip.es/linux/creating-a-vrf-and-running-services-inside-it-on-linux/
Update: I found out an alternative solution: Rather than enabling services for the specific VRF, which turned out to be quite complex, you can enable services in the global routing table to be available for all VRFs.
The Intent
Like the post before, The goal is to have a dedicated MGMT interface for incoming SSH and HTTPS traffic. All other traffic takes a different path.
Configuration
VRF Configuration
To create a VRF in Debian, these commands are used:
ip link add OOBM type vrf table 100
ip link set dev OOBM up
ip link set dev ens18 master OOBM
ip -6 address add fc00::3:3/64 dev ens18
ip -6 route add table 100 ::/0 via fc00::1 dev ens18
Explanation:
OOBM is the VRF name
ens18 is an interface that gets assigned to vrf OOBM
You can verify that routing works with following command:
~# ip -6 route show vrf OOBM
fc00::/64 dev ens18 proto kernel metric 256 pref medium
fe80::/64 dev ens18 proto kernel metric 256 pref medium
multicast ff00::/8 dev ens18 proto kernel metric 256 pref medium
default via fc00::1 dev ens18 metric 1024 pref medium
Make the configuration persistent
To make this configuration persistent through reboot, you can add it to the /etc/network/interface file:
~# nano /etc/network/interface
iface eno1 inet6 manual
auto OOBM
iface OOBM inet6 manual
pre-up ip link add $IFACE type vrf table 100
up ip link set dev $IFACE up
auto ens18
iface ens18 inet6 manual
up ip link set dev $IFACE master OOBM
up ip -6 address add fc00::3:B/64 dev $IFACE
up ip -6 route add default table 100 via fc00::1 dev $IFACE
Update: Enable services to listen to all VRFs
Source: https://docs.kernel.org/networking/vrf.html
Add following sysctl commands to enable all services for all VRFs:
sysctl -w net.ipv4.tcp_l3mdev_accept=1
sysctl -w net.ipv4.udp_l3mdev_accept=1
You can make them persistent by creating a .conf file in the sysctl.d directory:
nano /etc/sysctl.d/VRFBindAll.conf
net.ipv4.tcp_l3mdev_accept=1
net.ipv4.udp_l3mdev_accept=1
Note: Strangely, even though it says ipv4, the services are reachable over IPv6 as well.
This could be a security issue but I have mitigated that by only allowing Remote MGMT on specific interfaces.
Appendix
Edit the SSH service to listen to the VRF
This is an alternative method but it had it’s caveats.
On Debian, this was simpler than on Ubuntu because there is no socket configuration.
~# systemctl edit ssh.service
### Editing /etc/systemd/system/ssh.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
ExecStart=
ExecStart=/bin/ip vrf exec OOBM /usr/sbin/sshd -D $SSHD_OPTS
### Lines below this comment will be discarded
~# systemctl daemon-reload
~# systemctl restart ssh
And now you can verify that the SSH service is running under the VRF OOBM:
~# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
Drop-In: /etc/systemd/system/ssh.service.d
└─override.conf
Active: active (running) since Fri 2025-03-28 19:42:36 CET; 14h ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 2143 (sshd)
Tasks: 1 (limit: 38051)
Memory: 4.8M
CPU: 175ms
CGroup: /system.slice/ssh.service
└─vrf
└─OOBM
└─2143 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
~# ip vrf pids OOBM
2143 sshd
Caveats discovered
SSH not possible when networking.service is restarted
The problem is that when networking.service is restarted, the VRF configuration is temporarily deleted. SSH then starts listening on a random interface:
~$ ss -tulp | grep ssh
tcp LISTEN 0 128 0.0.0.0%if13:ssh 0.0.0.0:*
tcp LISTEN 0 128 [::]%if13:ssh [::]:*
This causes the reconnection to become refused. It is resolved by restarting ssh.service. However, I have not found out a good solution to restart ssh.service automatically after the network is restarted. I have tried some fine tuning but it always endsup in creating some unintended side-effects.
The best workaround so far is to restart only the interfaces that has been changed:
$ sudo ifdown dummy0
RTNETLINK answers: Cannot assign requested address
$ sudo ifup dummy0
Note: You can ignore the error. The changes still takes effect