Host-only adapters create a local virtual network, and routed TUN tunnels carry IP packets between addresses. Neither one is a bridge to the other, which is why a working configuration has to say who forwards and who owns the return route. Get those two assignments wrong and the guest answers the tunnel with a source the tunnel client never asked for. The design below keeps both prefixes distinct and makes the return path explicit.

Two networks, two prefixes

Give the tunnel pool and the host-only network different prefixes and never reuse one for the other. In this example the VPN pool is 10.44.0.0/24 and the host-only network is 192.168.99.0/24, with the host at 192.168.99.1 and a guest at 192.168.99.20. Assigning the same prefix to both a TUN device and the host-only adapter does not join them. It creates two claims on one address range, and the routing table then answers for whichever claim it happened to keep.

The host-only adapter exists on the host and inside the guest, and it has no path off the machine by itself. Bridged and NAT attachments have different exposure, and switching to bridged mode is not a requirement for reaching one guest service.

The host already holds the path

Look at what exists before adding anything. The host has an interface on the host-only network and a route for that prefix, both created when the adapter came up.

ip -br addr show
ip route show 192.168.99.0/24
sysctl net.ipv4.ip_forward

The third line is the mechanism that turns the host into a hop. Without it, a packet arriving from the tunnel is addressed to a network the host can reach but will not forward to. Forwarding is necessary and not sufficient. The filter policy still decides whether a particular flow between the tunnel interface and the host-only interface is allowed, and that decision belongs in writing rather than in a default policy nobody read.

Push the route, then filter what it reaches

The server can supply the host-only prefix to clients that accept pushed routes, which is the same mechanism used for any other subnet behind the tunnel.

push "route 192.168.99.0 255.255.255.0"
iptables -A FORWARD -i tun0 -o vboxnet0 -d 192.168.99.20 -p tcp --dport 5432 -j ACCEPT
iptables -A FORWARD -i vboxnet0 -o tun0 -s 192.168.99.20 -p tcp --sport 5432 -m conntrack --ctstate ESTABLISHED -j ACCEPT

Those two rules permit one service in one direction and its replies. A route that reaches the whole prefix and a filter that permits one port is a deliberate combination; a route plus an unconditional accept is how a lab service becomes an exposed one. A pushed route is also not authorization. The client accepts it, the host forwards it, and the guest firewall and the service itself still get a vote.

The guest needs a way back

A guest reached from 10.44.0.x has to send its replies to the host's host-only address, or the host has to translate the source. Receiving an address from VirtualBox DHCP says nothing about either arrangement.

ip route add 10.44.0.0/24 via 192.168.99.1 dev enp0s8
ip route get 10.44.0.15

Adding that route inside the guest preserves the original source, which keeps per-client policy and logs meaningful. Scoped source translation on the host is the alternative, and it works, at the cost of hiding which client connected. Overlap is the other failure mode. A remote client whose home LAN already uses 192.168.99.0/24 will read the pushed route as its own network, and no server-side change fixes that ambiguity. Renumber one side or pick a prefix unlikely to collide.

A TUN device carries IP packets, so adding a default gateway inside a guest does not turn the tunnel into an Ethernet segment with the host-only adapter. TAP bridging is a different design with its own client support and address ownership, and mixing the two descriptions leads to configurations that never converge.

Verify, then make it survive a restart

Test one harmless service from an ordinary remote client, check the guest's return route, and confirm that a service you did not permit is refused rather than slow.

ss -lntp '( sport = :5432 )'
conntrack -L | grep 192.168.99.20

Then restart the VPN service and the virtual machine networking, and repeat the same three checks. A route added by hand survives until the next reboot, and a configuration that only works in a warm session is not a design. Record the two prefixes, the forwarding policy and the guest route together. Whoever adds the next virtual machine will need all three and will otherwise rediscover them one failed connection at a time.

Sɛbɛn minnu bɛ tali kɛ