How to reach a VM running on a host server from outside, when the VM uses the default virbr0 (NAT) network. (Topology: external server A ↔ host server B ↔ VM A inside host B)
[01] Create Ubuntu VM Image
Install Package
1
|
sudo apt-get -y install nginx net-tools vim
|
Edit Nginx index.html
- Useful to confirm the request actually reaches the VM
- File:
/var/www/html/index.nginx-debian.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<!-- Edited: -VM -->
<h1>Welcome to nginx!-VM</h1>
<p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p>
</body>
</html>
|
Restart:
Forward Packets Between Host Server and VM
- Requests arriving at host server B on a specific port should be forwarded to the internal VM.
- Uses iptables
nat and filter tables
- Without
-t, the filter table is used by default.
1
2
|
iptables -t nat -A PREROUTING -i enp0s31f6 -p tcp -m tcp --dport 9999 -j DNAT --to-destination 192.168.122.131:80
iptables -I FORWARD -o virbr0 -d 192.168.122.131 -p tcp --dport 80 -j ACCEPT
|
- Rule (1)
-
enp0s31f6 is host server B’s NIC name
-
--dport 9999 matches requests arriving at host B’s NIC on port 9999
-
--to-destination 192.168.122.131:80 forwards them to the VM at 192.168.122.131 port 80
- Net effect: all traffic to host B port 9999 → VM port 80
- Rule (2)
-
-o virbr0 matches packets leaving host B via virbr0
-
-d 192.168.122.131 -p tcp --dport 80 matches that VM IP/port via TCP
-
-j ACCEPT allows the packet
- Net effect: opens the firewall so the forwarded packets can pass through
Persist Rules Across Server Restarts
1
2
3
4
5
6
7
8
9
10
11
|
# Install and start
sudo apt-get update
sudo apt-get install iptables-persistent
# Stop
sudo systemctl stop netfilter-persistent
sudo systemctl disable netfilter-persistent
# Restart
sudo systemctl enable netfilter-persistent
sudo systemctl start netfilter-persistent
|
1
2
3
4
5
6
7
8
9
10
|
# Save
sudo iptables-save > /etc/iptables/rules.v4
# Rename/backup
sudo mv /etc/iptables/rules.v4 /etc/iptables/rules.v4.backup
sudo mv /etc/iptables/rules.v6 /etc/iptables/rules.v6.backup
# Remove
sudo rm /etc/iptables/rules.v4
sudo rm /etc/iptables/rules.v6
|
(Reference) iptables Tables
Logical groups for filtering and manipulating packets
- Filter
- Packet filtering / firewall policy
- Decides allow/deny
- Chains: INPUT, OUTPUT, FORWARD
- NAT
- Network Address Translation and port forwarding
- Chains: PREROUTING, POSTROUTING
- Mangle
- Modify specific packet attributes (path, priority)
- Raw
- Handle exceptions to connection tracking
(Reference) iptables Chains
Sets of rules applied at specific stages of packet flow
- INPUT: packets entering the local system
- OUTPUT: packets generated by the local system
- FORWARD: packets routed through the system (router role)
- PREROUTING: applied before routing — used for port forwarding, source address rewriting
- POSTROUTING: applied after routing — typically for NAT (source/destination rewriting)
(Reference) iptables Commands
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# Inspect rules
sudo iptables -t nat --line-numbers -L PREROUTING
sudo iptables -t filter --line-numbers -L FORWARD
# List with addresses
sudo iptables -t filter -L -n
sudo iptables -t nat -L -n
sudo iptables -t mangle -L -n
sudo iptables -t raw -L -n
# Delete a specific rule
sudo iptables -t nat -D PREROUTING ${line-number}
sudo iptables -t filter -D FORWARD ${line-number}
|
(Reference) virsh Commands
1
2
3
4
5
6
7
8
9
10
|
# List VMs
virsh list
# IP address of a specific VM
virsh domifaddr ${id}
virsh domifaddr ${name}
# All DHCP addresses
virsh net-dhcp-leases ${interface_name}
# e.g.: virsh net-dhcp-leases default
|
[04] Verify Access
- ServerIP + Forwarding (iptables) Port
- e.g.,
111.111.111.111:9999
- Uses port 9999 from [03]
- Confirm
<h1>Welcome to nginx!-VM</h1> from [02] is displayed