Commit daecbbd0 by Őry Máté

Port forwarding support for ONE

parent d44640cd
......@@ -3,7 +3,7 @@ from firewall.models import *
class HostAdmin(admin.ModelAdmin):
list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'mac', 'owner', 'groups_l', 'rules_l', 'description')
list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'pub_ipv4', 'mac', 'shared_ip', 'owner', 'groups_l', 'rules_l', 'description')
ordering = ('hostname',)
list_filter = ('owner', 'vlan', 'groups')
search_fields = ('hostname', 'description', 'ipv4', 'ipv6', 'mac')
......
......@@ -180,14 +180,14 @@ class firewall:
#portforward
for host in self.hosts.filter(pub_ipv4=None):
for host in self.hosts.exclude(pub_ipv4=None):
for rule in host.rules.filter(nat=True, direction=True):
dport_sport = self.dportsport(rule, False)
if host.vlan.snat_ip:
self.iptablesnat("-A PREROUTING -d %s %s %s -j DNAT --to-destination %s:%s" % (host.vlan.snat_ip, dport_sport, rule.extra, host.ipv4, rule.nat_dport))
self.iptablesnat("-A PREROUTING -d %s %s %s -j DNAT --to-destination %s:%s" % (host.pub_ipv4, dport_sport, rule.extra, host.ipv4, rule.nat_dport))
#sajat publikus ipvel rendelkezo gepek szabalyai
for host in self.hosts:
for host in self.hosts.exclude(shared_ip=True):
if(host.pub_ipv4):
self.iptablesnat("-A PREROUTING -d %s -j DNAT --to-destination %s" % (host.pub_ipv4, host.ipv4))
self.iptablesnat("-A POSTROUTING -s %s -j SNAT --to-source %s" % (host.ipv4, host.pub_ipv4))
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Removing unique constraint on 'Host', fields ['pub_ipv4']
db.delete_unique('firewall_host', ['pub_ipv4'])
def backwards(self, orm):
# Adding unique constraint on 'Host', fields ['pub_ipv4']
db.create_unique('firewall_host', ['pub_ipv4'])
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'firewall.firewall': {
'Meta': {'object_name': 'Firewall'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
},
'firewall.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'})
},
'firewall.host': {
'Meta': {'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'rules': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Rule']", 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
},
'firewall.rule': {
'Meta': {'object_name': 'Rule'},
'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'direction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'vlan': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
},
'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
'rules': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'firewall_vlan_related'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['firewall.Rule']"}),
'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
}
}
complete_apps = ['firewall']
\ No newline at end of file
from django.contrib.auth.models import User
from django.db import models
from django.forms import fields
from django.forms import fields, ValidationError
from django.utils.translation import ugettext_lazy as _
from firewall.fields import *
from south.modelsinspector import add_introspection_rules
......@@ -85,8 +85,9 @@ class Host(models.Model):
hostname = models.CharField(max_length=20, unique=True, validators=[val_alfanum])
mac = MACAddressField(unique=True)
ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
pub_ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True, blank=True, null=True)
pub_ipv4 = models.GenericIPAddressField(protocol='ipv4', blank=True, null=True)
ipv6 = models.GenericIPAddressField(protocol='ipv6', unique=True, blank=True)
shared_ip = models.BooleanField(default=False)
description = models.TextField(blank=True)
comment = models.TextField(blank=True)
location = models.TextField(blank=True)
......@@ -100,6 +101,8 @@ class Host(models.Model):
def save(self, *args, **kwargs):
if not self.id and not self.ipv6:
self.ipv6 = ipv4_2_ipv6(self.ipv4)
if not self.shared_ip and self.pub_ipv4 and Host.objects.filter(pub_ipv4=self.pub_ipv4):
raise ValidationError("Ha a shared_ip be van pipalva, akkor egyedinek kell lennie a pub_ipv4-nek!")
super(Host, self).save(*args, **kwargs)
def groups_l(self):
retval = []
......@@ -112,6 +115,37 @@ class Host(models.Model):
retval.append(str(rl))
return ', '.join(retval)
def EnableNet(self):
rule = Rule(direction=False, owner=self.owner, description="%s netezhet" % (self.hostname), accept=True, r_type="host")
rule.save()
rule.vlan.add(Vlan.objects.get(name="PUB"))
self.rules.add(rule)
def AddPort(self, proto, public, private):
proto = "tcp" if (proto == "tcp") else "udp"
for host in Host.objects.filter(pub_ipv4=self.pub_ipv4):
if host.rules.filter(nat=True, proto=proto, dport=public):
raise ValidationError("A %s %s port mar hasznalva" % (proto, public))
rule = Rule(direction=True, owner=self.owner, description="%s %s %s->%s" % (self.hostname, proto, public, private), dport=public, proto=proto, nat=True, accept=True, r_type="host", nat_dport=private)
rule.full_clean()
rule.save()
rule.vlan.add(Vlan.objects.get(name="PUB"))
rule.vlan.add(Vlan.objects.get(name="DMZ"))
rule.vlan.add(Vlan.objects.get(name="VM-NET"))
rule.vlan.add(Vlan.objects.get(name="WAR"))
self.rules.add(rule)
def DelPort(self, proto, public):
self.rules.filter(owner=self.owner, proto=proto, nat=True, dport=public).delete()
def ListPorts(self):
retval = []
for rule in self.rules.filter(owner=self.owner, nat=True):
retval.append({'public': rule.dport, 'private': rule.nat_dport})
return retval
def DelRules(self):
self.rules.filter(owner=self.owner).delete()
class Firewall(models.Model):
name = models.CharField(max_length=20, unique=True)
......
from celery.task import Task, PeriodicTask
from django.core.cache import cache
import os
import time
from firewall.fw import *
LOCK_EXPIRE = 9 # Lock expires in 5 minutes
lock_id = "blabla"
def lock(para):
def reload_firewall_lock():
acquire_lock = lambda: cache.add(lock_id, "true", LOCK_EXPIRE)
if acquire_lock():
print "megszereztem"
ReloadTask.delay("asd")
ReloadTask.delay()
else:
print "nem szereztem meg"
class ReloadTask(Task):
def run(self, para, **kwargs):
def run(self, **kwargs):
print "indul"
os.system("sleep 10")
time.sleep(10)
try:
print "ipv4"
ipv4 = firewall()
# html += ipv4.show()
ipv4.reload()
# print ipv4.show()
print "ipv6"
ipv6 = firewall(True)
ipv6.reload()
......
......@@ -18,23 +18,8 @@ def reload_firewall(request):
if request.user.is_authenticated():
if(request.user.is_superuser):
html = u"Be vagy jelentkezve es admin is vagy, kedves %s!" % request.user.username
try:
print "ipv4"
ipv4 = firewall()
# html += ipv4.show()
ipv4.reload()
print "ipv6"
ipv6 = firewall(True)
ipv6.reload()
print "dns"
dns()
print "dhcp"
dhcp()
print "vege"
html += "<br>sikerult :)"
except:
raise
html += "<br>nem sikerult :("
html += "<br> 10 masodperc mulva ujratoltodik"
ReloadTask.delay()
else:
html = u"Be vagy jelentkezve, csak nem vagy admin, kedves %s!" % request.user.username
else:
......@@ -55,24 +40,14 @@ def firewall_api(request):
if(command == "create"):
data["owner"] = "opennebula"
owner = auth.models.User.objects.get(username=data["owner"])
host = models.Host(hostname=data["hostname"], vlan=models.Vlan.objects.get(name=data["vlan"]), mac=data["mac"], ipv4=data["ip"], owner=owner, description=data["description"])
host = models.Host(hostname=data["hostname"], vlan=models.Vlan.objects.get(name=data["vlan"]), mac=data["mac"], ipv4=data["ip"], owner=owner, description=data["description"], pub_ipv4=models.Vlan.objects.get(name=data["vlan"]).snat_ip, shared_ip=True)
host.full_clean()
host.save()
rule = models.Rule(direction=False, owner=owner, description="%s netezhet" % (data["hostname"]), accept=True, r_type="host", nat_dport=0)
rule.save()
rule.vlan.add(models.Vlan.objects.get(name="PUB"))
host.rules.add(rule)
host.EnableNet()
for p in data["portforward"]:
proto = "tcp" if (p["proto"] == "tcp") else "udp"
rule = models.Rule(direction=True, owner=owner, description="%s %s %s->%s" % (data["hostname"], proto, p["public_port"], p["private_port"]), dport=int(p["public_port"]), proto=p["proto"], nat=True, accept=True, r_type="host", nat_dport=int(p["private_port"]))
rule.save()
rule.vlan.add(models.Vlan.objects.get(name="PUB"))
rule.vlan.add(models.Vlan.objects.get(name="DMZ"))
rule.vlan.add(models.Vlan.objects.get(name="VM-NET"))
rule.vlan.add(models.Vlan.objects.get(name="WAR"))
host.rules.add(rule)
host.AddPort(proto=p["proto"], public=int(p["public_port"]), private=int(p["private_port"]))
elif(command == "destroy"):
data["owner"] = "opennebula"
......@@ -80,14 +55,12 @@ def firewall_api(request):
owner = auth.models.User.objects.get(username=data["owner"])
host = models.Host.objects.get(hostname=data["hostname"], owner=owner)
for rule in host.rules.filter(owner=owner):
rule.delete()
host.DelRules()
host.delete()
else:
raise Exception("rossz parancs")
lock("asd")
reload_firewall_lock()
except (ValidationError, IntegrityError, AttributeError, Exception) as e:
return HttpResponse(u"rosszul hasznalod! :(\n%s\n" % e);
except:
......@@ -96,6 +69,12 @@ def firewall_api(request):
return HttpResponse(u"ok");
host = models.Host.objects.get(hostname="id-298-ubuntu-teszt2")
print host.ListPorts()
try:
host.AddPort("udp", 31337, 3133)
except:
host.DelPort("udp", 31337)
return HttpResponse(u"ez kerlek egy api lesz!\n");
......@@ -9,7 +9,10 @@ from django import forms
from django.utils.translation import ugettext_lazy as _
from one.util import keygen
from school.models import Person
import subprocess, tempfile, os, stat
from firewall.models import Host, Rule, Vlan
from firewall.tasks import reload_firewall_lock
import subprocess, tempfile, os, stat, re
pwgen = User.objects.make_random_password
......@@ -187,6 +190,7 @@ class Instance(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
state = models.CharField(max_length=20, choices=[('DEPLOYABLE', 'DEPLOYABLE'), ('PENDING', 'PENDING'), ('DONE', 'DONE'), ('ACTIVE', 'ACTIVE'),('UNKNOWN', 'UNKNOWN'), ('SUSPENDED', 'SUSPENDED'), ('FAILED', 'FAILED')], default='DEPLOYABLE')
active_since = models.DateTimeField(null=True, blank=True)
firewall_host = models.ForeignKey(Host, blank=True, null=True)
pw = models.CharField(max_length=20)
one_id = models.IntegerField(unique=True, blank=True, null=True)
def get_port(self):
......@@ -277,6 +281,7 @@ class Instance(models.Model):
<NETWORK href="http://www.opennebula.org/network/%(net)d"/>
</NIC>
<CONTEXT>
<SOURCE>web</SOURCE>
<HOSTNAME>cloud-$VMID</HOSTNAME>
<NEPTUN>%(neptun)s</NEPTUN>
<USERPW>%(pw)s</USERPW>
......@@ -313,12 +318,27 @@ class Instance(models.Model):
inst.name = "%(neptun)s %(template)s (%(id)d)" % {'neptun': owner.username, 'template': template.name, 'id': inst.one_id}
inst.save()
inst.update_state()
host = Host(vlan=Vlan.objects.get(name=template.network.name), owner=owner, shared_ip=True)
host.hostname = u"id-%d_user-%s" % (inst.id, owner.username)
host.mac = x.getElementsByTagName("MAC")[0].childNodes[0].nodeValue
host.ipv4 = inst.ip
host.pub_ipv4 = "152.66.243.161"
host.full_clean()
host.save()
host.EnableNet()
host.AddPort("tcp", inst.get_port(), {"rdp": 3389, "nx": 22, "ssh": 22}[inst.template.access_type])
inst.firewall_host=host
inst.save()
reload_firewall_lock()
return inst
def delete(self):
proc = subprocess.Popen(["/opt/occi.sh", "compute",
"delete", "%d"%self.one_id], stdout=subprocess.PIPE)
(out, err) = proc.communicate()
self.firewall_host.DelRules()
self.firewall_host.delete()
reload_firewall_lock()
class Meta:
verbose_name = _('instance')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment