Commit 6b20ceba by Bach Dániel

firewall: rename firewall fields

parent 79d910dc
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
"hostname": "devenv", "hostname": "devenv",
"modified_at": "2014-02-24T15:55:01.412Z", "modified_at": "2014-02-24T15:55:01.412Z",
"location": "", "location": "",
"pub_ipv4": null,
"mac": "11:22:33:44:55:66", "mac": "11:22:33:44:55:66",
"shared_ip": false, "shared_ip": false,
"ipv4": "10.7.0.96", "ipv4": "10.7.0.96",
......
...@@ -16,7 +16,7 @@ class RecordInline(contrib.admin.TabularInline): ...@@ -16,7 +16,7 @@ class RecordInline(contrib.admin.TabularInline):
class HostAdmin(admin.ModelAdmin): class HostAdmin(admin.ModelAdmin):
list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'pub_ipv4', 'mac', list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'external_ipv4', 'mac',
'shared_ip', 'owner', 'description', 'reverse', 'shared_ip', 'owner', 'description', 'reverse',
'list_groups') 'list_groups')
ordering = ('hostname', ) ordering = ('hostname', )
...@@ -49,7 +49,7 @@ class VlanAdmin(admin.ModelAdmin): ...@@ -49,7 +49,7 @@ class VlanAdmin(admin.ModelAdmin):
class RuleAdmin(admin.ModelAdmin): class RuleAdmin(admin.ModelAdmin):
list_display = ('r_type', 'color_desc', 'owner', 'extra', 'direction', list_display = ('r_type', 'color_desc', 'owner', 'extra', 'direction',
'accept', 'proto', 'sport', 'dport', 'nat', 'accept', 'proto', 'sport', 'dport', 'nat',
'nat_dport', 'used_in') 'nat_external_port', 'used_in')
list_filter = ('vlan', 'owner', 'direction', 'accept', list_filter = ('vlan', 'owner', 'direction', 'accept',
'proto', 'nat') 'proto', 'nat')
......
# -*- 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):
# Renaming field 'Host.pub_ipv4' to 'Host.external_ipv4'
db.rename_column(u'firewall_host', 'pub_ipv4', 'external_ipv4')
# Renaming field 'Rule.nat_dport' to 'Rule.nat_external_port'
db.rename_column(u'firewall_rule', 'nat_dport', 'nat_external_port')
# Adding field 'Rule.priority'
db.add_column(u'firewall_rule', 'priority',
self.gf('django.db.models.fields.IntegerField')(default=1000, null=True, blank=True),
keep_default=False)
# Adding field 'Rule.nat_external_ipv4'
db.add_column(u'firewall_rule', 'nat_external_ipv4',
self.gf('firewall.fields.IPAddressField')(max_length=100, null=True, blank=True),
keep_default=False)
# Changing field 'Rule.direction'
db.alter_column(u'firewall_rule', 'direction', self.gf('django.db.models.fields.CharField')(max_length=3))
# Migrating data
for rule in orm.Rule.objects.all():
if rule.nat:
# swap
tmp = rule.dport
# rule.dport = rule.nat_external_port
# rule.nat_external_port = tmp
if rule.direction == '0':
rule.direction = 'out'
elif rule.direction == '1':
rule.direction = 'in'
rule.save()
def backwards(self, orm):
# Renaming field 'Host.external_ipv4' to 'Host.pub_ipv4'
db.rename_column(u'firewall_host', 'external_ipv4', 'pub_ipv4')
# Renaming field 'Rule.nat_external_port' to 'Rule.nat_dport'
db.rename_column(u'firewall_rule', 'nat_external_port', 'nat_dport')
# Deleting field 'Rule.priority'
db.delete_column(u'firewall_rule', 'priority')
# Deleting field 'Rule.nat_external_ipv4'
db.delete_column(u'firewall_rule', 'nat_external_ipv4')
# Changing field 'Rule.direction'
db.alter_column(u'firewall_rule', 'direction', self.gf('django.db.models.fields.CharField')(max_length=3))
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.IntegerField', [], {}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'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'}),
u'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'})
},
u'firewall.blacklist': {
'Meta': {'object_name': 'Blacklist'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'snort_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'default': "'tempban'", 'max_length': '10'})
},
u'firewall.domain': {
'Meta': {'object_name': 'Domain'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
},
u'firewall.ethernetdevice': {
'Meta': {'object_name': 'EthernetDevice'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'switch_port': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ethernet_devices'", 'to': u"orm['firewall.SwitchPort']"})
},
u'firewall.firewall': {
'Meta': {'object_name': 'Firewall'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
},
u'firewall.group': {
'Meta': {'object_name': 'Group'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
u'firewall.host': {
'Meta': {'ordering': "('normalized_hostname', 'vlan')", 'unique_together': "(('hostname', 'vlan'),)", 'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'external_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('firewall.fields.IPAddressField', [], {'unique': 'True', 'max_length': '100'}),
'ipv6': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'normalized_hostname': ('common.models.HumanSortField', [], {'default': "''", 'maximum_number_length': '4', 'max_length': '80', 'monitor': "'hostname'", 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Vlan']"})
},
u'firewall.record': {
'Meta': {'ordering': "('domain', 'name')", 'object_name': 'Record'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
},
u'firewall.rule': {
'Meta': {'ordering': "('direction', 'proto', 'sport', 'dport', 'nat_external_port', 'host')", 'object_name': 'Rule'},
'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'direction': ('django.db.models.fields.CharField', [], {'max_length': '3'}),
'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Firewall']"}),
'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': u"orm['firewall.VlanGroup']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Host']"}),
'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'nat_external_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'nat_external_port': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {'default': '1000', 'null': 'True', 'blank': 'True'}),
'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Vlan']"}),
'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.VlanGroup']"})
},
u'firewall.switchport': {
'Meta': {'object_name': 'SwitchPort'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'tagged_vlans': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tagged_ports'", 'null': 'True', 'to': u"orm['firewall.VlanGroup']"}),
'untagged_vlan': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'untagged_ports'", 'to': u"orm['firewall.Vlan']"})
},
u'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv6_template': ('django.db.models.fields.TextField', [], {'default': "'2001:738:2001:4031:%(b)d:%(c)d:%(d)d:0'"}),
'managed': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'network4': ('firewall.fields.IPNetworkField', [], {'max_length': '100'}),
'network6': ('firewall.fields.IPNetworkField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'network_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {'default': "'%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa'"}),
'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': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
u'firewall.vlangroup': {
'Meta': {'object_name': 'VlanGroup'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['firewall']
# -*- 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):
# Changing field 'Rule.priority'
db.alter_column(u'firewall_rule', 'priority', self.gf('django.db.models.fields.IntegerField')())
def backwards(self, orm):
# Changing field 'Rule.priority'
db.alter_column(u'firewall_rule', 'priority', self.gf('django.db.models.fields.IntegerField')(null=True))
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.IntegerField', [], {}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'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'}),
u'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'})
},
u'firewall.blacklist': {
'Meta': {'object_name': 'Blacklist'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'snort_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'default': "'tempban'", 'max_length': '10'})
},
u'firewall.domain': {
'Meta': {'object_name': 'Domain'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
},
u'firewall.ethernetdevice': {
'Meta': {'object_name': 'EthernetDevice'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'switch_port': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ethernet_devices'", 'to': u"orm['firewall.SwitchPort']"})
},
u'firewall.firewall': {
'Meta': {'object_name': 'Firewall'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
},
u'firewall.group': {
'Meta': {'object_name': 'Group'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
u'firewall.host': {
'Meta': {'ordering': "('normalized_hostname', 'vlan')", 'unique_together': "(('hostname', 'vlan'),)", 'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'external_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('firewall.fields.IPAddressField', [], {'unique': 'True', 'max_length': '100'}),
'ipv6': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'normalized_hostname': ('common.models.HumanSortField', [], {'default': "''", 'maximum_number_length': '4', 'max_length': '80', 'monitor': "'hostname'", 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Vlan']"})
},
u'firewall.record': {
'Meta': {'ordering': "('domain', 'name')", 'object_name': 'Record'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
},
u'firewall.rule': {
'Meta': {'ordering': "('direction', 'proto', 'sport', 'dport', 'nat_external_port', 'host')", 'object_name': 'Rule'},
'accept': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'direction': ('django.db.models.fields.CharField', [], {'max_length': '3'}),
'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Firewall']"}),
'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': u"orm['firewall.VlanGroup']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Host']"}),
'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'nat_external_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'nat_external_port': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {'default': '1000'}),
'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.Vlan']"}),
'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': u"orm['firewall.VlanGroup']"})
},
u'firewall.switchport': {
'Meta': {'object_name': 'SwitchPort'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'tagged_vlans': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tagged_ports'", 'null': 'True', 'to': u"orm['firewall.VlanGroup']"}),
'untagged_vlan': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'untagged_ports'", 'to': u"orm['firewall.Vlan']"})
},
u'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv6_template': ('django.db.models.fields.TextField', [], {'default': "'2001:738:2001:4031:%(b)d:%(c)d:%(d)d:0'"}),
'managed': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'network4': ('firewall.fields.IPNetworkField', [], {'max_length': '100'}),
'network6': ('firewall.fields.IPNetworkField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'network_type': ('django.db.models.fields.CharField', [], {'default': "'portforward'", 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {'default': "'%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa'"}),
'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': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
u'firewall.vlangroup': {
'Meta': {'object_name': 'VlanGroup'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['firewall']
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
from itertools import islice, ifilter from itertools import islice, ifilter
import logging import logging
from netaddr import IPSet, EUI from netaddr import IPSet, EUI, IPNetwork
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
...@@ -19,6 +19,7 @@ import random ...@@ -19,6 +19,7 @@ import random
from common.models import HumanSortField from common.models import HumanSortField
from firewall.tasks.local_tasks import reloadtask from firewall.tasks.local_tasks import reloadtask
from .iptables import IptRule
from acl.models import AclBase from acl.models import AclBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
settings = django.conf.settings.FIREWALL_SETTINGS settings = django.conf.settings.FIREWALL_SETTINGS
...@@ -36,9 +37,9 @@ class Rule(models.Model): ...@@ -36,9 +37,9 @@ class Rule(models.Model):
CHOICES_type = (('host', 'host'), ('firewall', 'firewall'), CHOICES_type = (('host', 'host'), ('firewall', 'firewall'),
('vlan', 'vlan')) ('vlan', 'vlan'))
CHOICES_proto = (('tcp', 'tcp'), ('udp', 'udp'), ('icmp', 'icmp')) CHOICES_proto = (('tcp', 'tcp'), ('udp', 'udp'), ('icmp', 'icmp'))
CHOICES_dir = (('0', 'out'), ('1', 'in')) CHOICES_dir = (('out', 'out'), ('in', 'in'))
direction = models.CharField(max_length=1, choices=CHOICES_dir, direction = models.CharField(max_length=3, choices=CHOICES_dir,
blank=False, verbose_name=_("direction"), blank=False, verbose_name=_("direction"),
help_text=_("If the rule matches egress " help_text=_("If the rule matches egress "
"or ingress packets.")) "or ingress packets."))
...@@ -58,28 +59,37 @@ class Rule(models.Model): ...@@ -58,28 +59,37 @@ class Rule(models.Model):
blank=True, null=True, verbose_name=_("source port"), blank=True, null=True, verbose_name=_("source port"),
validators=[MinValueValidator(1), MaxValueValidator(65535)], validators=[MinValueValidator(1), MaxValueValidator(65535)],
help_text=_("Source port number of packets that match.")) help_text=_("Source port number of packets that match."))
priority = models.IntegerField(
verbose_name=_("priority"),
validators=[MinValueValidator(1), MaxValueValidator(65535)],
help_text=_("TODO"),
default=1000)
proto = models.CharField(max_length=10, choices=CHOICES_proto, proto = models.CharField(max_length=10, choices=CHOICES_proto,
blank=True, null=True, verbose_name=_("protocol"), blank=True, null=True, verbose_name=_("protocol"),
help_text=_("Protocol of packets that match.")) help_text=_("Protocol of packets that match."))
extra = models.TextField(blank=True, verbose_name=_("extra arguments"), extra = models.TextField(blank=True, verbose_name=_("extra arguments"),
help_text=_("Additional arguments passed " help_text=_("Additional arguments passed "
"literally to the iptables-rule.")) "literally to the iptables-rule."))
accept = models.BooleanField(default=False, verbose_name=_("accept"), accept = models.BooleanField(default=True, verbose_name=_("accept"),
help_text=_("Accept the matching packets " help_text=_("Accept the matching packets "
"(or deny if not checked).")) "(or deny if not checked)."))
owner = models.ForeignKey(User, blank=True, null=True, owner = models.ForeignKey(User, blank=True, null=True,
verbose_name=_("owner"), verbose_name=_("owner"),
help_text=_("The user responsible for " help_text=_("The user responsible for "
"this rule.")) "this rule."))
nat = models.BooleanField(default=False, verbose_name=_("NAT"), nat = models.BooleanField(default=False, verbose_name=_("NAT"),
help_text=_("If network address translation " help_text=_("If network address translation "
"should be done.")) "should be done."))
nat_dport = models.IntegerField(blank=True, null=True, nat_external_port = models.IntegerField(
help_text=_("Rewrite destination port " blank=True, null=True,
"number to this if NAT is " help_text=_("Rewrite destination port number to this if NAT is "
"needed."), "needed."),
validators=[MinValueValidator(1), validators=[MinValueValidator(1), MaxValueValidator(65535)])
MaxValueValidator(65535)]) nat_external_ipv4 = IPAddressField(
version=4, blank=True, null=True,
verbose_name=_('external IPv4 address'))
created_at = models.DateTimeField( created_at = models.DateTimeField(
auto_now_add=True, auto_now_add=True,
verbose_name=_("created at")) verbose_name=_("created at"))
...@@ -120,14 +130,28 @@ class Rule(models.Model): ...@@ -120,14 +130,28 @@ class Rule(models.Model):
if len(selected_fields) > 1: if len(selected_fields) > 1:
raise ValidationError(_('Only one field can be selected.')) raise ValidationError(_('Only one field can be selected.'))
def get_external_ipv4(self):
return (self.nat_external_ipv4
if self.nat_external_ipv4 else self.host.get_external_ipv4())
def get_external_ipv6(self):
return self.host.ipv6
def get_external_port(self, proto='ipv4'):
assert proto in ('ipv4', 'ipv6')
if proto == 'ipv4' and self.nat_external_port:
return self.nat_external_port
else:
return self.dport
def desc(self): def desc(self):
"""Return a short string representation of the current rule. """Return a short string representation of the current rule.
""" """
return u'[%(type)s] %(src)s ▸ %(dst)s %(para)s %(desc)s' % { return u'[%(type)s] %(src)s ▸ %(dst)s %(para)s %(desc)s' % {
'type': self.r_type, 'type': self.r_type,
'src': (unicode(self.foreign_network) if self.direction == '1' 'src': (unicode(self.foreign_network) if self.direction == 'in'
else self.r_type), else self.r_type),
'dst': (self.r_type if self.direction == '1' 'dst': (self.r_type if self.direction == 'out'
else unicode(self.foreign_network)), else unicode(self.foreign_network)),
'para': ((("proto=%s " % self.proto) if self.proto else '') + 'para': ((("proto=%s " % self.proto) if self.proto else '') +
(("sport=%s " % self.sport) if self.sport else '') + (("sport=%s " % self.sport) if self.sport else '') +
...@@ -147,6 +171,60 @@ class Rule(models.Model): ...@@ -147,6 +171,60 @@ class Rule(models.Model):
def get_absolute_url(self): def get_absolute_url(self):
return ('network.rule', None, {'pk': self.pk}) return ('network.rule', None, {'pk': self.pk})
@staticmethod
def get_chain_name(local, remote, direction):
if direction == 'in':
# remote -> local
return '%s_%s' % (remote, local)
else:
# local -> remote
return '%s_%s' % (local, remote)
def get_ipt_rules(self, host=None):
# action
action = 'LOG_ACC' if self.accept else 'LOG_DROP'
# src and dst addresses
src = None
dst = None
if host:
ip = (host.ipv4, host.ipv6_with_prefixlen)
if self.direction == 'in':
dst = ip
else:
src = ip
# src and dst ports
if self.direction == 'in':
dport = self.dport
sport = self.sport
else:
dport = self.sport
sport = self.dport
# 'chain_name': rule dict
retval = {}
# process foreign vlans
for foreign_vlan in self.foreign_network.vlans.all():
r = IptRule(priority=self.priority, action=action,
proto=self.proto, extra=self.extra,
src=src, dst=dst, dport=dport, sport=sport)
# host, hostgroup or vlan rule
if host or self.vlan_id:
local_vlan = host.vlan.name if host else self.vlan.name
chain_name = Rule.get_chain_name(local=local_vlan,
remote=foreign_vlan.name,
direction=self.direction)
# firewall rule
elif self.firewall_id:
chain_name = 'INPUT' if self.direction == 'in' else 'OUTPUT'
retval[chain_name] = r
return retval
class Meta: class Meta:
verbose_name = _("rule") verbose_name = _("rule")
verbose_name_plural = _("rules") verbose_name_plural = _("rules")
...@@ -155,7 +233,7 @@ class Rule(models.Model): ...@@ -155,7 +233,7 @@ class Rule(models.Model):
'proto', 'proto',
'sport', 'sport',
'dport', 'dport',
'nat_dport', 'nat_external_port',
'host', 'host',
) )
...@@ -177,7 +255,7 @@ class Vlan(AclBase, models.Model): ...@@ -177,7 +255,7 @@ class Vlan(AclBase, models.Model):
('user', _('user')), ('user', _('user')),
('operator', _('operator')), ('operator', _('operator')),
) )
CHOICES_NETWORK_TYPE = (('public', _('public')), ('dmz', _('dmz')), CHOICES_NETWORK_TYPE = (('public', _('public')),
('portforward', _('portforward'))) ('portforward', _('portforward')))
vid = models.IntegerField(unique=True, vid = models.IntegerField(unique=True,
verbose_name=_('VID'), verbose_name=_('VID'),
...@@ -226,6 +304,7 @@ class Vlan(AclBase, models.Model): ...@@ -226,6 +304,7 @@ class Vlan(AclBase, models.Model):
'of NAT IP address.')) 'of NAT IP address.'))
network_type = models.CharField(choices=CHOICES_NETWORK_TYPE, network_type = models.CharField(choices=CHOICES_NETWORK_TYPE,
verbose_name=_('network type'), verbose_name=_('network type'),
default='portforward',
max_length=20) max_length=20)
managed = models.BooleanField(default=True, verbose_name=_('managed')) managed = models.BooleanField(default=True, verbose_name=_('managed'))
description = models.TextField(blank=True, verbose_name=_('description'), description = models.TextField(blank=True, verbose_name=_('description'),
...@@ -403,7 +482,7 @@ class Host(models.Model): ...@@ -403,7 +482,7 @@ class Host(models.Model):
verbose_name=_('IPv4 address'), verbose_name=_('IPv4 address'),
help_text=_('The real IPv4 address of the ' help_text=_('The real IPv4 address of the '
'host, for example 10.5.1.34.')) 'host, for example 10.5.1.34.'))
pub_ipv4 = IPAddressField( external_ipv4 = IPAddressField(
version=4, blank=True, null=True, version=4, blank=True, null=True,
verbose_name=_('WAN IPv4 address'), verbose_name=_('WAN IPv4 address'),
help_text=_('The public IPv4 address of the host on the wide ' help_text=_('The public IPv4 address of the host on the wide '
...@@ -449,18 +528,31 @@ class Host(models.Model): ...@@ -449,18 +528,31 @@ class Host(models.Model):
@property @property
def incoming_rules(self): def incoming_rules(self):
return self.rules.filter(direction='1') return self.rules.filter(direction='in')
@property @property
def outgoing_rules(self): def ipv6_with_prefixlen(self):
return self.rules.filter(direction='0') try:
net = IPNetwork(self.ipv6)
net.prefixlen = 112
return net
except TypeError:
return None
def get_external_ipv4(self):
return self.external_ipv4 if self.external_ipv4 else self.ipv4
@property
def behind_nat(self):
return self.vlan.network_type != 'public'
def clean(self): def clean(self):
if (not self.shared_ip and self.pub_ipv4 and Host.objects. if (self.external_ipv4 and not self.shared_ip and self.behind_nat
exclude(id=self.id).filter(pub_ipv4=self.pub_ipv4)): and Host.objects.exclude(id=self.id).filter(
external_ipv4=self.external_ipv4)):
raise ValidationError(_("If shared_ip has been checked, " raise ValidationError(_("If shared_ip has been checked, "
"pub_ipv4 has to be unique.")) "external_ipv4 has to be unique."))
if Host.objects.exclude(id=self.id).filter(pub_ipv4=self.ipv4): if Host.objects.exclude(id=self.id).filter(external_ipv4=self.ipv4):
raise ValidationError(_("You can't use another host's NAT'd " raise ValidationError(_("You can't use another host's NAT'd "
"address as your own IPv4.")) "address as your own IPv4."))
...@@ -517,12 +609,15 @@ class Host(models.Model): ...@@ -517,12 +609,15 @@ class Host(models.Model):
:type proto: str. :type proto: str.
:returns: list -- list of int port numbers used. :returns: list -- list of int port numbers used.
""" """
if self.shared_ip: if self.behind_nat:
ports = Rule.objects.filter(host__pub_ipv4=self.pub_ipv4, ports = Rule.objects.filter(
nat=True, proto=proto) host__external_ipv4=self.external_ipv4,
nat=True,
proto=proto).values_list('nat_external_port', flat=True)
else: else:
ports = self.rules.filter(proto=proto, ) ports = self.rules.filter(proto=proto).values_list(
return set(ports.values_list('dport', flat=True)) 'dport', flat=True)
return set(ports)
def _get_random_port(self, proto, used_ports=None): def _get_random_port(self, proto, used_ports=None):
""" """
...@@ -577,17 +672,15 @@ class Host(models.Model): ...@@ -577,17 +672,15 @@ class Host(models.Model):
logger.error('Host.add_port: default_vlangroup %s missing. %s', logger.error('Host.add_port: default_vlangroup %s missing. %s',
vgname, unicode(e)) vgname, unicode(e))
else: else:
if self.shared_ip: rule = Rule(direction='in', owner=self.owner, dport=private,
proto=proto, nat=False, accept=True,
host=self, foreign_network=vg)
if self.behind_nat:
if public < 1024: if public < 1024:
raise ValidationError( raise ValidationError(
_("Only ports above 1024 can be used.")) _("Only ports above 1024 can be used."))
rule = Rule(direction='1', owner=self.owner, dport=public, rule.nat_external_port = public
proto=proto, nat=True, accept=True, rule.nat = True
nat_dport=private, host=self, foreign_network=vg)
else:
rule = Rule(direction='1', owner=self.owner, dport=private,
proto=proto, nat=False, accept=True,
host=self, foreign_network=vg)
rule.full_clean() rule.full_clean()
rule.save() rule.save()
...@@ -602,12 +695,8 @@ class Host(models.Model): ...@@ -602,12 +695,8 @@ class Host(models.Model):
:param private: Port number of host in subject. :param private: Port number of host in subject.
""" """
if self.shared_ip: self.rules.filter(owner=self.owner, proto=proto, host=self,
self.rules.filter(owner=self.owner, proto=proto, host=self, dport=private).delete()
nat_dport=private).delete()
else:
self.rules.filter(owner=self.owner, proto=proto, host=self,
dport=private).delete()
def get_hostname(self, proto, public=True): def get_hostname(self, proto, public=True):
""" """
...@@ -622,11 +711,11 @@ class Host(models.Model): ...@@ -622,11 +711,11 @@ class Host(models.Model):
res = self.record_set.filter(type='AAAA', res = self.record_set.filter(type='AAAA',
address=self.ipv6) address=self.ipv6)
elif proto == 'ipv4': elif proto == 'ipv4':
if self.shared_ip and public: if self.behind_nat and public:
res = Record.objects.filter(type='A', res = Record.objects.filter(
address=self.pub_ipv4) type='A', address=self.get_external_ipv4())
if res.count() < 1: if res.count() < 1:
return unicode(self.pub_ipv4) return unicode(self.get_external_ipv4())
else: else:
res = self.record_set.filter(type='A', res = self.record_set.filter(type='A',
address=self.ipv4) address=self.ipv4)
...@@ -640,27 +729,21 @@ class Host(models.Model): ...@@ -640,27 +729,21 @@ class Host(models.Model):
""" """
retval = [] retval = []
for rule in self.rules.filter(owner=self.owner): for rule in self.rules.filter(owner=self.owner):
private = rule.nat_dport if self.shared_ip else rule.dport
forward = { forward = {
'proto': rule.proto, 'proto': rule.proto,
'private': private, 'private': rule.dport,
} }
if self.shared_ip:
public4 = rule.dport
public6 = rule.nat_dport
else:
public4 = public6 = rule.dport
if True: # ipv4 if True: # ipv4
forward['ipv4'] = { forward['ipv4'] = {
'host': self.get_hostname(proto='ipv4'), 'host': self.get_hostname(proto='ipv4'),
'port': public4, 'port': rule.get_external_port(proto='ipv4'),
'pk': rule.pk, 'pk': rule.pk,
} }
if self.ipv6: # ipv6 if self.ipv6: # ipv6
forward['ipv6'] = { forward['ipv6'] = {
'host': self.get_hostname(proto='ipv6'), 'host': self.get_hostname(proto='ipv6'),
'port': public6, 'port': rule.get_external_port(proto='ipv6'),
'pk': rule.pk, 'pk': rule.pk,
} }
retval.append(forward) retval.append(forward)
...@@ -679,18 +762,12 @@ class Host(models.Model): ...@@ -679,18 +762,12 @@ class Host(models.Model):
""" """
endpoints = {} endpoints = {}
# IPv4 # IPv4
public_ipv4 = self.pub_ipv4 if self.pub_ipv4 else self.ipv4
# try get matching port(s) without NAT
ports = self.incoming_rules.filter(accept=True, dport=port, ports = self.incoming_rules.filter(accept=True, dport=port,
nat=False, proto=protocol) proto=protocol)
if ports.exists(): public_port = (ports[0].get_external_port(proto='ipv4')
public_port = ports[0].dport if ports.exists() else None)
else: endpoints['ipv4'] = ((self.get_external_ipv4(), public_port)
# try get matching port(s) with NAT if public_port else
ports = self.incoming_rules.filter(accept=True, nat_dport=port,
nat=True, proto=protocol)
public_port = ports[0].dport if ports.exists() else None
endpoints['ipv4'] = ((public_ipv4, public_port) if public_port else
None) None)
# IPv6 # IPv6
blocked = self.incoming_rules.filter(accept=False, dport=port, blocked = self.incoming_rules.filter(accept=False, dport=port,
......
...@@ -48,7 +48,7 @@ def periodic_task(): ...@@ -48,7 +48,7 @@ def periodic_task():
@celery.task @celery.task
def reloadtask(type='Host'): def reloadtask(type='Host', timeout=15):
reload = { reload = {
'Host': ['dns', 'dhcp', 'firewall'], 'Host': ['dns', 'dhcp', 'firewall'],
'Record': ['dns'], 'Record': ['dns'],
......
...@@ -96,12 +96,12 @@ class HostGetHostnameTestCase(TestCase): ...@@ -96,12 +96,12 @@ class HostGetHostnameTestCase(TestCase):
self.vlan.save() self.vlan.save()
self.h = Host(hostname='h', mac='01:02:03:04:05:00', ipv4='10.0.0.1', self.h = Host(hostname='h', mac='01:02:03:04:05:00', ipv4='10.0.0.1',
vlan=self.vlan, owner=self.u1, shared_ip=True, vlan=self.vlan, owner=self.u1, shared_ip=True,
pub_ipv4=self.vlan.snat_ip) external_ipv4=self.vlan.snat_ip)
self.h.save() self.h.save()
def test_issue_93_wo_record(self): def test_issue_93_wo_record(self):
self.assertEqual(self.h.get_hostname(proto='ipv4', public=True), self.assertEqual(self.h.get_hostname(proto='ipv4', public=True),
unicode(self.h.pub_ipv4)) unicode(self.h.external_ipv4))
def test_issue_93_w_record(self): def test_issue_93_w_record(self):
self.r = Record(name='vm', type='A', domain=self.d, owner=self.u1, self.r = Record(name='vm', type='A', domain=self.d, owner=self.u1,
......
...@@ -167,7 +167,8 @@ class RuleForm(ModelForm): ...@@ -167,7 +167,8 @@ class RuleForm(ModelForm):
'accept', 'accept',
'owner', 'owner',
'nat', 'nat',
'nat_dport', 'nat_external_port',
'nat_external_ipv4',
), ),
Fieldset( Fieldset(
'External', 'External',
......
...@@ -128,7 +128,8 @@ class RuleTable(Table): ...@@ -128,7 +128,8 @@ class RuleTable(Table):
model = Rule model = Rule
attrs = {'class': 'table table-striped table-hover table-condensed'} attrs = {'class': 'table table-striped table-hover table-condensed'}
fields = ('r_type', 'color_desc', 'owner', 'extra', 'direction', fields = ('r_type', 'color_desc', 'owner', 'extra', 'direction',
'accept', 'proto', 'sport', 'dport', 'nat', 'nat_dport', ) 'accept', 'proto', 'sport', 'dport', 'nat',
'nat_external_port', )
order_by = 'direction' order_by = 'direction'
......
...@@ -33,5 +33,6 @@ ...@@ -33,5 +33,6 @@
{% if record.nat %} {% if record.nat %}
<span class="label label-success">NAT <span class="label label-success">NAT
[ {{ record.dport }} <i class="icon-arrow-right"></i> {{record.nat_dport}} ]</span> [ {{ record.dport }} <i class="icon-arrow-right"></i>
{{record.nat_external_port}} ]</span>
{% endif %} {% endif %}
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