diff --git a/firewall/admin.py b/firewall/admin.py index f142bfa..c07c8b8 100644 --- a/firewall/admin.py +++ b/firewall/admin.py @@ -102,6 +102,9 @@ class RecordAdmin(admin.ModelAdmin): if a: return a['name'] +class BlacklistAdmin(admin.ModelAdmin): + list_display = ('ipv4', 'reason', 'created_at', 'modified_at') + admin.site.register(Host, HostAdmin) admin.site.register(Vlan, VlanAdmin) admin.site.register(Rule, RuleAdmin) @@ -110,4 +113,5 @@ admin.site.register(VlanGroup) admin.site.register(Firewall, FirewallAdmin) admin.site.register(Domain, DomainAdmin) admin.site.register(Record, RecordAdmin) +admin.site.register(Blacklist, BlacklistAdmin) diff --git a/firewall/fw.py b/firewall/fw.py index d41f9cb..a0d14d0 100644 --- a/firewall/fw.py +++ b/firewall/fw.py @@ -6,6 +6,7 @@ from cloud.settings import firewall_settings as settings import subprocess import re import json +from datetime import datetime, timedelta class firewall: @@ -17,6 +18,7 @@ class firewall: pub = None hosts = None fw = None + ipset = None def dportsport(self, rule, repl=True): retval = ' ' @@ -133,13 +135,14 @@ class firewall: self.iptables('-N PUB_OUT') + self.iptables('-A FORWARD -m set --match-set blacklist src,dst -j DROP') self.iptables('-A FORWARD -m state --state INVALID -g LOG_DROP') self.iptables('-A FORWARD -m state --state ESTABLISHED,RELATED ' '-j ACCEPT') self.iptables('-A FORWARD -p icmp --icmp-type echo-request ' '-g LOG_ACC') - if not self.IPV6: - self.iptables('-A FORWARD -j r_pub_sIP -o pub') + + self.iptables('-A INPUT -m set --match-set blacklist src -j DROP') self.iptables('-A INPUT -m state --state INVALID -g LOG_DROP') self.iptables('-A INPUT -i lo -j ACCEPT') self.iptables('-A INPUT -m state --state ESTABLISHED,RELATED ' @@ -260,6 +263,7 @@ class firewall: def __init__(self, IPV6=False): self.RULES=[] self.RULES_NAT=[] + self.IPSET = [] self.IPV6 = IPV6 self.vlans = models.Vlan.objects.all() self.hosts = models.Host.objects.all() @@ -269,6 +273,7 @@ class firewall: self.ipt_filter() if not self.IPV6: self.ipt_nat() + self.IPSET=self.ipset() def reload(self): if self.IPV6: @@ -287,7 +292,7 @@ class firewall: if self.IPV6: return { 'filter': self.RULES, } else: - return { 'filter': self.RULES, 'nat':self.RULES_NAT } + return { 'filter': self.RULES, 'nat': self.RULES_NAT, 'ipset': self.IPSET } def show(self): if self.IPV6: @@ -296,6 +301,10 @@ class firewall: return ('\n'.join(self.RULES) + '\n' + '\n'.join(self.RULES_NAT) + '\n') + def ipset(self): + week = datetime.now()-timedelta(days=7) + return models.Blacklist.objects.filter(modified_at__gte=week).values_list('ipv4', flat=True) + def ipv6_to_octal(ipv6): while len(ipv6.split(':')) < 8: diff --git a/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py b/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py new file mode 100644 index 0000000..8995adf --- /dev/null +++ b/firewall/migrations/0030_auto__del_setting__del_alias__add_blacklist.py @@ -0,0 +1,213 @@ +# -*- 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): + # Deleting model 'Setting' + db.delete_table('firewall_setting') + + # Deleting model 'Alias' + db.delete_table('firewall_alias') + + # Adding model 'Blacklist' + db.create_table('firewall_blacklist', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('ipv4', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)), + ('reason', self.gf('django.db.models.fields.TextField')(blank=True)), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('firewall', ['Blacklist']) + + + def backwards(self, orm): + # Adding model 'Setting' + db.create_table('firewall_setting', ( + ('value', self.gf('django.db.models.fields.CharField')(max_length=200)), + ('description', self.gf('django.db.models.fields.TextField')(blank=True)), + ('key', self.gf('django.db.models.fields.CharField')(max_length=32)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('firewall', ['Setting']) + + # Adding model 'Alias' + db.create_table('firewall_alias', ( + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('modified_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + ('alias', self.gf('django.db.models.fields.CharField')(max_length=40, unique=True)), + ('host', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'])), + ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('firewall', ['Alias']) + + # Deleting model 'Blacklist' + db.delete_table('firewall_blacklist') + + + 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.blacklist': { + 'Meta': {'object_name': 'Blacklist'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + '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'}) + }, + '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'}), + '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': "orm['auth.User']"}), + 'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}) + }, + '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'}) + }, + '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'}), + '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': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'firewall.host': { + 'Meta': {'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'}), + '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': '40'}), + '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', [], {'max_length': '39', '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'}), + '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'}), + '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': "orm['firewall.Vlan']"}) + }, + 'firewall.record': { + 'Meta': {'object_name': 'Record'}, + 'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + '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': "orm['firewall.Domain']"}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}), + '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': "orm['auth.User']"}), + 'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '6'}) + }, + 'firewall.rule': { + 'Meta': {'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': '1'}), + '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': "orm['firewall.Firewall']"}), + 'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}), + 'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}), + '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_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.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}), + 'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"}) + }, + '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': "orm['firewall.Domain']"}), + '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'}), + 'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + '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'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}), + 'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}), + 'reverse_domain': ('django.db.models.fields.TextField', [], {}), + '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'}) + }, + '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'}), + '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': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['firewall'] \ No newline at end of file diff --git a/firewall/models.py b/firewall/models.py index a4ae403..6ebee44 100644 --- a/firewall/models.py +++ b/firewall/models.py @@ -318,6 +318,11 @@ class Record(models.Model): return None return retval +class Blacklist(models.Model): + ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True) + reason = models.TextField(blank=True) + created_at = models.DateTimeField(auto_now_add=True) + modified_at = models.DateTimeField(auto_now=True) def send_task(sender, instance, created, **kwargs): from firewall.tasks import ReloadTask @@ -332,3 +337,4 @@ post_save.connect(send_task, sender=Vlan) post_save.connect(send_task, sender=Firewall) post_save.connect(send_task, sender=Group) post_save.connect(send_task, sender=Host) +post_save.connect(send_task, sender=Blacklist)