Connect vif's to already running VMs on NetVM/ProxyVM startup (#190)
Also cleanup stale vifs using "xm network-detach ... -f" Fix iptables rules to support not only first vif of VM
This commit is contained in:
parent
655f13e2ec
commit
98f4028142
@ -5,7 +5,8 @@ netmask=`/usr/bin/xenstore-read qubes_netmask`
|
|||||||
gateway=`/usr/bin/xenstore-read qubes_gateway`
|
gateway=`/usr/bin/xenstore-read qubes_gateway`
|
||||||
secondary_dns=`/usr/bin/xenstore-read qubes_secondary_dns`
|
secondary_dns=`/usr/bin/xenstore-read qubes_secondary_dns`
|
||||||
if [ x$ip != x ]; then
|
if [ x$ip != x ]; then
|
||||||
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255 up
|
/sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255
|
||||||
|
/sbin/ifconfig $INTERFACE up
|
||||||
/sbin/route add default dev $INTERFACE
|
/sbin/route add default dev $INTERFACE
|
||||||
echo "nameserver $gateway" > /etc/resolv.conf
|
echo "nameserver $gateway" > /etc/resolv.conf
|
||||||
echo "nameserver $secondary_dns" >> /etc/resolv.conf
|
echo "nameserver $secondary_dns" >> /etc/resolv.conf
|
||||||
|
@ -543,6 +543,28 @@ class QubesVm(object):
|
|||||||
f_private.truncate (size)
|
f_private.truncate (size)
|
||||||
f_private.close ()
|
f_private.close ()
|
||||||
|
|
||||||
|
def cleanup_vifs(self):
|
||||||
|
"""
|
||||||
|
Xend does not remove vif when backend domain is down, so we must do it
|
||||||
|
manually
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.is_running():
|
||||||
|
return
|
||||||
|
|
||||||
|
p = subprocess.Popen (["/usr/sbin/xm", "network-list", self.name],
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
result = p.communicate()
|
||||||
|
for line in result[0].split('\n'):
|
||||||
|
m = re.match(r"^(\d+)\s*(\d+)", line)
|
||||||
|
if m:
|
||||||
|
retcode = subprocess.call(["/usr/sbin/xm", "list", m.group(2)],
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
if retcode != 0:
|
||||||
|
# Don't check retcode - it always will fail when backend domain is down
|
||||||
|
subprocess.call(["/usr/sbin/xm",
|
||||||
|
"network-detach", self.name, m.group(1), "-f"], stderr=subprocess.PIPE)
|
||||||
|
|
||||||
def create_xenstore_entries(self, xid):
|
def create_xenstore_entries(self, xid):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
return
|
return
|
||||||
@ -1371,6 +1393,29 @@ class QubesNetVm(QubesVm):
|
|||||||
|
|
||||||
return subprocess.check_call(command)
|
return subprocess.check_call(command)
|
||||||
|
|
||||||
|
def start(self, debug_console = False, verbose = False, preparing_dvm=False):
|
||||||
|
if dry_run:
|
||||||
|
return
|
||||||
|
|
||||||
|
xid=super(QubesNetVm, self).start(debug_console=debug_console, verbose=verbose)
|
||||||
|
|
||||||
|
# Connect vif's of already running VMs
|
||||||
|
for vm in self.connected_vms.values():
|
||||||
|
if not vm.is_running():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print "--> Attaching network to '{0}'...".format(vm.name)
|
||||||
|
|
||||||
|
# Cleanup stale VIFs
|
||||||
|
vm.cleanup_vifs()
|
||||||
|
|
||||||
|
xm_cmdline = ["/usr/sbin/xm", "network-attach", vm.name, "script=vif-route-qubes", "ip="+vm.ip, "backend="+self.name ]
|
||||||
|
retcode = subprocess.call (xm_cmdline)
|
||||||
|
if retcode != 0:
|
||||||
|
print ("WARNING: Cannot attach to network to '{0}'!".format(vm.name))
|
||||||
|
return xid
|
||||||
|
|
||||||
def add_external_ip_permission(self, xid):
|
def add_external_ip_permission(self, xid):
|
||||||
if int(xid) < 0:
|
if int(xid) < 0:
|
||||||
return
|
return
|
||||||
@ -1471,7 +1516,7 @@ class QubesProxyVm(QubesNetVm):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
iptables += "# '{0}' VM:\n".format(vm.name)
|
iptables += "# '{0}' VM:\n".format(vm.name)
|
||||||
iptables += "-A FORWARD ! -s {0}/32 -i vif{1}.0 -j DROP\n".format(vm.ip, xid)
|
iptables += "-A FORWARD ! -s {0}/32 -i vif{1}.+ -j DROP\n".format(vm.ip, xid)
|
||||||
|
|
||||||
accept_action = "ACCEPT"
|
accept_action = "ACCEPT"
|
||||||
reject_action = "REJECT --reject-with icmp-host-prohibited"
|
reject_action = "REJECT --reject-with icmp-host-prohibited"
|
||||||
@ -1484,7 +1529,7 @@ class QubesProxyVm(QubesNetVm):
|
|||||||
rules_action = accept_action
|
rules_action = accept_action
|
||||||
|
|
||||||
for rule in conf["rules"]:
|
for rule in conf["rules"]:
|
||||||
iptables += "-A FORWARD -i vif{0}.0 -d {1}".format(xid, rule["address"])
|
iptables += "-A FORWARD -i vif{0}.+ -d {1}".format(xid, rule["address"])
|
||||||
if rule["netmask"] != 32:
|
if rule["netmask"] != 32:
|
||||||
iptables += "/{0}".format(rule["netmask"])
|
iptables += "/{0}".format(rule["netmask"])
|
||||||
|
|
||||||
@ -1497,12 +1542,12 @@ class QubesProxyVm(QubesNetVm):
|
|||||||
|
|
||||||
if conf["allowDns"]:
|
if conf["allowDns"]:
|
||||||
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm_vm. properties
|
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm_vm. properties
|
||||||
iptables += "-A FORWARD -i vif{0}.0 -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.gateway)
|
iptables += "-A FORWARD -i vif{0}.+ -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.gateway)
|
||||||
iptables += "-A FORWARD -i vif{0}.0 -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.secondary_dns)
|
iptables += "-A FORWARD -i vif{0}.+ -p udp -d {1} --dport 53 -j ACCEPT\n".format(xid,self.netvm_vm.secondary_dns)
|
||||||
if conf["allowIcmp"]:
|
if conf["allowIcmp"]:
|
||||||
iptables += "-A FORWARD -i vif{0}.0 -p icmp -j ACCEPT\n".format(xid)
|
iptables += "-A FORWARD -i vif{0}.+ -p icmp -j ACCEPT\n".format(xid)
|
||||||
|
|
||||||
iptables += "-A FORWARD -i vif{0}.0 -j {1}\n".format(xid, default_action)
|
iptables += "-A FORWARD -i vif{0}.+ -j {1}\n".format(xid, default_action)
|
||||||
|
|
||||||
iptables += "#End of VM rules\n"
|
iptables += "#End of VM rules\n"
|
||||||
iptables += "-A FORWARD -j DROP\n"
|
iptables += "-A FORWARD -j DROP\n"
|
||||||
|
@ -166,6 +166,9 @@ def main():
|
|||||||
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
|
parser.add_option ("--localcmd", action="store", dest="localcmd", default=None,
|
||||||
help="With --pass_io, pass stdin/stdout/stderr to the given program")
|
help="With --pass_io, pass stdin/stdout/stderr to the given program")
|
||||||
|
|
||||||
|
parser.add_option ("--force", action="store_true", dest="force", default=False,
|
||||||
|
help="Force operation, even if may damage other VMs (eg shutdown of NetVM)")
|
||||||
|
|
||||||
(options, args) = parser.parse_args ()
|
(options, args) = parser.parse_args ()
|
||||||
|
|
||||||
|
|
||||||
@ -218,8 +221,12 @@ def main():
|
|||||||
|
|
||||||
# If stopping NetVM - stop connected VMs too
|
# If stopping NetVM - stop connected VMs too
|
||||||
if options.shutdown and vm.is_netvm():
|
if options.shutdown and vm.is_netvm():
|
||||||
vms_list += [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
|
connected_vms = [vm for vm in qvm_collection.get_vms_connected_to(vm.qid) if vm.is_running()]
|
||||||
vms_list.reverse()
|
if connected_vms and not options.force:
|
||||||
|
print "ERROR: There are other VMs connected to this VM, "
|
||||||
|
print " shutdown them first or use --force option"
|
||||||
|
print "VMs list: " + str([vm.name for vm in connected_vms])
|
||||||
|
exit(1)
|
||||||
|
|
||||||
if takes_cmd_argument:
|
if takes_cmd_argument:
|
||||||
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
|
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
|
||||||
|
Loading…
Reference in New Issue
Block a user