That means "no way in" for external connections. The virtual network addresses are unseen (unroutable) to the outside world.
Luckily, libvirtd provides hooks so that you can insert custom operations at key points in the start-up/shut-down phases of a guest. The following procedure shows how to create a hook to modify iptables when a guest is starting (or stopping).
- On the host, create a new file called
/etc/libvirt/hooks/qemucontaining this sample script. (There's a link to a more comprehensive script if you need it. I also wrote a Python replacement below.) - Replace the placeholder variables in the sample script with the guest name, addresses, and ports that are to be forwarded.
- Restart the libvirt service.
- Verify new DNAT rules with
iptables -nvL -t nat.
As an exercise, I rewrote the sample script in Python, adding some logging and removing some redundancy along the way.
#!/usr/bin/env python
#!/usr/bin/env python
import argparse
import logging
import subprocess
import sys
guestAddr = { 'f17-base':'192.168.122.200' }
hostPort = { '80':'8000', '22':'222' }
logFile = '/var/log/qemu-hook.log'
logLevel = logging.DEBUG
logging.basicConfig(filename=logFile, level=logLevel, format='%(asctime)s : %(message)s')
parser = argparse.ArgumentParser()
for arg in [ 'guest', 'op', 'subop', 'extra' ]:
parser.add_argument(arg)
args = parser.parse_args()
logging.debug('qemu hook: guest %s, op %s' % (args.guest, args.op))
if args.guest not in guestAddr:
logging.debug('Nothing to do for guest %s' % args.guest)
sys.exit()
if args.op == 'start':
natOp = '-A'
filterOp = '-I'
opStr = 'Adding'
elif args.op == 'stopped':
natOp = filerOp = '-D'
opStr = 'Removing'
else:
logging.debug('Nothing to do for op %s' % args.op)
sys.exit()
for gport in hostPort.keys():
# build the nat command
natcmd = ['iptables', '-t', 'nat', natOp, 'PREROUTING']
gAddrPort = "{}:{}".format(guestAddr[args.guest], gport)
natcmd += ['-p', 'tcp', '--dport', hostPort[gport], '-j', 'DNAT', '--to', gAddrPort]
logging.info('%s nat rules for %s' % (opStr, gAddrPort))
subprocess.call(natcmd)
# build the filter command
filtercmd = ['iptables', filterOp, 'FORWARD']
filtercmd += ['-d', '{}/32'.format(guestAddr[args.guest]), '-p', 'tcp']
filtercmd += ['-m', 'state', '--state', 'NEW']
filtercmd += ['-m', 'tcp', '--dport', gport, '-j', 'ACCEPT']
logging.info('%s forwarding rules for %s' % (opStr, gport))
subprocess.call(filtercmd)
logging.info('iptables update complete')
sys.exit()
Note that, depending on the version of libvirtd you are running, the hook may not process "reconnect" operations -- i.e., when libvirtd is restarted. You need 0.9.13 or later for that. If you have an earlier version, you may have an issue with duplicate rules.
I left those operations out of the Python script because my Fedora 17 system is running 0.9.11.
Cheers!
No comments:
Post a Comment