I have a server with one external IP address (e.g. On that server I use libvirt to run virtual machines. Now I want to access a virtual server on my host via ssh (port 1234) from the outside.

On my host system I got a network interface eth0 which is connected to my outside IP (

My virtual machine is connected to the host machine via a nat interface called virbr0 with the ip

As I need to forward a port I did the following with iptable

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 1234 -j DNAT --to-destination

iptables -A FORWARD -p tcp -d --dport 1234 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

For basic networking I also got UFW running on the host allows port 1234:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), allow (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
1234/tcp                  ALLOW IN    Anywhere
1234/tcp (v6)             ALLOW IN    Anywhere (v6)

I made sure that forwarding is allowed for all involved network interfaces:

user@someserver ~ # cat /proc/sys/net/ipv4/conf/virbr0/forwarding 
user@someserver ~ # cat /proc/sys/net/ipv4/conf/eth0/forwarding 

When trying to connect via ssh to the server from the outside network to I get:

ssh: connect to host port 1234: Connection refused

I checked the ssh connection from the host, which is working perfectly.

  • What am I doing wrong here?
  • Does UFW interfere with iptables?
  • How can I get this working?
  • Is there an easier way to do port forwarding with libvirt / virt-manager? (I tried this: http://secomputing.co.uk/2012/02/21/Forwarding-ports-to-KVM-clients/ which did not work either because XML is not valid when changing to / it does validate but not work if I let it on "network")
  • Is running an SSH server listening on 1234 or is it listening on 22 and you want something to NAT incoming requests for 1234 to 22? Also, please post the output of iptables -nvL. Apr 16, 2016 at 16:10
  • @user5870571 the SSH server is really listening on 1234 (which stands for another port it's just a placeholder). I can connect from the host machine without any issues.
    – Flatron
    Apr 16, 2016 at 16:12

4 Answers 4


I had virtually the same issue. I wanted to forward port 22 from my host machine to my VM, also running KVM, with NAT network.

I found this post: https://ubuntuforums.org/showthread.php?t=2261173&p=13210545#post13210545

Which had the answers for me.

TL;DR is my servers IP on the internal network. is my VMs ip on the host.

iptables -t nat -I PREROUTING -p tcp -d --dport 22 -j DNAT --to-destination
iptables -I FORWARD -m state -d --state NEW,RELATED,ESTABLISHED -j ACCEPT 

Disclaimer. I have no idea what this does exactly. It looks the same as many other answers ive found, just some of the parameter tags being slightly different.

  • That's the only one worked really, thanks
    – HXH
    Feb 8, 2021 at 17:45
  • Yeah! You made my day
    – alwaysday1
    Mar 30, 2023 at 9:29

There are a few things we should consider.

What am I doing wrong here?

Let's see the current iptables config and then we can examine it.

Does UFW interfere with iptables?

UFW is a command line front end for iptables but it lacks many of the features of iptables. Having the iptables configuration will show us what UFW has done based on the commands you entered. You should not however, create rules with both on the same computer. That is asking for complications. If you are going to enter your commands in UFW fine but iptables scripts should be disabled. If you are going to enter your commands in iptables then you should remove UFW.

How can I get this working?

Try this.

iptables -t nat -I PREROUTING -p tcp -i eth0 --dport 1234 -j DNAT --to

iptables -A FORWARD -i eth0 -o vibr0 -p tcp --dport 1234 -j ACCEPT

But keep in mind that the guest is connected to the host using NAT with the adapter. So this probably won't work.

What you really should consider is changing the adapter type from NAT to bridged.


I think also you should use a bridged connection:

Try to find out your name of the network:

 virsh net-edit <network name>

The name of the network you can see in the Virt Manager. Normally it's default:

 virsh net-edit default

Change from NAT to bridge (also the Bridge name you find in Virt Manager)

   <forward mode='route'/>
   <bridge name='virbr0' stp='on' delay='0'/>
   <mac address='AA:CC:DD:86:53:54'/>
   <ip address='' netmask=''>
         <range start='' end=''/>


  • In the example we used DHCP to give names to the VM's. You can also make static settings

  • If you use ifconfig you should get:

    virbr0 Link encap:Ethernet Hardware Adresse AA:VV:CC:86:53:54
    inet Adresse: Bcast: Maske: UP BROADCAST RUNNING MULTICAST MTU:1500 Metrik:1 RX-Pakete:127 Fehler:0 Verloren:0 Überläufe:0 Fenster:0 TX-Pakete:44 Fehler:0 Verloren:0 Überläufe:0 Träger:0 Kollisionen:0 Sendewarteschlangenlänge:0 RX-Bytes:13032 (13.0 KB) TX-Bytes:4707 (4.7 KB)

  • Basically you should use port 22 for ssh

  • Try to use:

    sudo iptables -t nat -A POSTROUTING -s -j SNAT --to-source

So you can localize if it's a problem with the ports. In fact you can after close the Ports on the VM with Gufw.

  • 1
    Thanks for your answer, our current issue is, we only have one outside IP so we cannot use bridge mode. If we could this would be no issue. But IPv4 addresses don't grow on trees. This is a setup with a hosting company, not a closed home network.
    – Flatron
    Apr 16, 2016 at 18:52
  • That could be difficult. In my case I was not able to setup the network with eth0 (Network card), Certainly it's not so good to mix up ufw and iptables. Perhaps in gufw you can setup advanced rules, where you can choose the IP address directly for forwarding... Apr 16, 2016 at 19:34

These are my forwarding rules which pretty well.

-A POSTROUTING -s ! -d -p tcp -j MASQUERADE --to-ports 1024-65535
-A POSTROUTING -s ! -d -p udp -j MASQUERADE --to-ports 1024-65535
-A FORWARD -d -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j ACCEPT
-A FORWARD -i br1 -o virbr0 -j ACCEPT

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .