Code Monkey home page Code Monkey logo

hknutzen / netspoc Goto Github PK

View Code? Open in Web Editor NEW
66.0 10.0 10.0 1.29 GB

A network security policy compiler. Netspoc is targeted at environments with a large number of firewalls and admins. Firewall rules are derived from a single rule set. Supported are Cisco IOS, NX-OS, ASA, Palo-Alto, VMware NSX gateway firewalls and IPTables.

Home Page: http://hknutzen.github.io/Netspoc

License: GNU General Public License v2.0

Perl 2.68% Makefile 0.01% C 0.11% Shell 0.25% Go 96.94%
nxos iptables packet-filter network-topology firewall cisco-ios golang firewall-configuration cisco cisco-asa

netspoc's Introduction

Netspoc

A network security policy compiler.

Test Status Coverage Status

Netspoc has been migrated from Perl to Go (golang). Released CPAN packages will contain compiled binaries for Linux-x86_64 architecture. These will be installed along with Perl scripts, typically in /usr/local/bin.

Netspoc is free software to manage all the packet filter devices inside your network topology. Filter rules for each device are generated from one central ruleset, using a description of your network topology.

  • Supports Cisco and Linux devices
    • Chains for iptables.
    • Access lists for ASA, NX-OS
    • Access lists for IOS with and without Firewall Feature Set.
  • Rules are optimized globally
    • Adjacent IP ranges and port ranges are joined.
    • Redundant rules are removed and optionally warned about.
  • Highly optimized chains for iptables are generated.
  • Object-groups for ASA and NX-OS are generated.
  • IPSec configuration for Cisco ASA, ASA and IOS is generated.
  • Commands for static routing are generated (optionally).
  • Network address translation (NAT) is supported.
  • HSRP / VRRP clusters are supported.
  • Multicast traffic for OSPF, EIGRP, HSRP, VRRP is supported.
  • Powerful rules language
    • Groups can be defined and reused in different rules.
    • Automatic groups utilize relationships of the topology.
  • Allows to define a secondary packet filter which gets simpler rules if a data stream has already been filtered at some other device.
  • Complex topologies with redundant paths are supported.
  • Pathrestrictions allow to restrict paths inside a redundant topology.

netspoc's People

Contributors

drachionix avatar hknutzen avatar mbruns avatar orrence avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

netspoc's Issues

Ambiguous {up} relation in protocols with src_range

Der Commit 7d29183 macht potentiell Probleme.
Das war etwas kurz gedacht.
Denn mit diesem Test-Case wird vor der Änderung noch die Regel mit p1 als redundant zur Regel mit p2 erkannt.

protocol:p1 = udp 123:123;
protocol:p2 = udp 1-65535:123;
protocol:p3 = udp 123:1-65535;
network:n1 = { ip = 10.1.1.0/24; }
router:r1 = {
  model = IOS, FW;
  managed;
  interface:n1 = { ip = 10.1.1.1; hardware = n1; }
  interface:n2 = { ip = 10.1.2.1; hardware = n2; }
}
network:n2 = { ip = 10.1.2.0/24; }
service:t1 = {
  user = network:n1;
  permit src = user; dst = network:n2; prt = protocol:p1, protocol:p2; 
}

Aktuell wird erkannt, dass p1 < p3, aber ignoriert, dass auch gilt p1 < p2.
Denn innerhalb von Protocols kann das nicht ausgedrückt werden, da p2 und p3 nicht vergleichbar sind, aber beide größer sind als p1.

Check aggregate rules during secondary optimization

Topologie:

src--R1--any--R2--dst
mit R1 ist "managed=secondary"

Regeln:

  1. permit any -> dst, telnet
  2. permit src -> dst, http

Generierte ACLs:

  • auf R1:
    • von 2.: permit net(src) net(dst) ip
  • auf R2:
    • von 1.: permit any dst telnet
    • von 2.: permit src dst http

Problem:

src soll nur mittels http auf dst zugreifen können, kann jedoch auch mittels telnet zugreifen.

Diskussion:

Bei der Generierung von Any-Regeln vertrauen wir darauf, dass Router
hinter dem any-Bereich (im Beispiel R1) die Zugriffe genügend
einschränken, so dass die Verwendung von any keine Lücke öffnet.
Bei der Code-Generierung für seconday Router vertrauen wir darauf, dass
ein normaler Router (im Beispiel R2) die detaillierte Filterung übernimmt.

Beides Zusammen kann jedoch zu einer Fehleinschätzung führen,
denn R1 verlässt sich auf R2 und umgekehrt.

Wie findet man diesen Fall?

Nicht so einfach.

Ansatz:

Für jede Regel any -> dst1, prt1
finde Regeln src -> dst2, prt2

  • mit dst2 <= dst1 (oder so ähnlich)
  • mit prt2 != prt1 und !(prt2 > prt1)
  • und any liegt auf dem Pfad zwischen src und dst2
  • und zwischen src und any liegen nur ein oder mehrere secondary Router

Das ist aufwändig, da Pfade bestimmt werden müssen.

Effizienter:

Alle Zonen sind bereits markiert mit {secondary_mark}.
Zwei Zonen haben die gleiche Markierung, wenn sie durch ein oder mehrere secondary Router verbunden sind.
Jedes Any liegt in genau einer Zone.

None

Bug report was intended for netspoc-web

Find useless NAT

When is a "bind_nat = x" useless?

  1. bind_nat is applied to an unmanaged device and
  2. the area where this bind_nat is applicable, has no managed device and
  3. this bind_nat doesn't prevent an address conflict.

How do we check this?

  1. is easy
  2. needs to find the area bordered by other occurences of "bind_nat = x".
    If this area is located inside a single zone or zone_cluster, then there is no managed device.
  3. we need to check all networks with nat:x and compare its address with all networks inside the bind_nat area. We can't always use the original address, but must check if some other NAT is applied.

This seems to be rather complex.

Must not mix rules from "managed=local" when finding object-groups

Netspoc combines multiple similar rules to one rule that references object-groups. Access-lists generated by Netspoc never have alternating deny and permit rules. It uses only one set of deny rules at the beginning and one set of permit rules at the end of an access-list. When combining rules, Netspoc can freely change the order of permit rules (and of deny rules).

But if the feature "managed = local" is enabled, additional deny rules are added at the end of an access-list and one additional permit any any rules is added at the very end.

In this situation, Netspoc combines unrelated permit rules by mistake.

Test case

network:n1 = { ip = 10.2.1.0/24; }

router:r = {
 model = ASA;
 managed = local;
 filter_only =  10.2.0.0/16;
 interface:n1 = { ip = 10.2.1.1; hardware = n1; }
 interface:n2 = { ip = 10.2.2.1; hardware = n2; }
}

network:n2 = { ip = 10.2.2.0/24; }

service:t1 = {
 user = any:[network:n1];
 permit src = user; dst = network:n2; prt = ip;
}

Error message:

Internal error in Netspoc::__ANON__: Unexpected object with mask 0  in object-group of router:r

at Netspoc/lib/Netspoc.pm line 16568

Use of uninitialized value on multiple invalid paths

Netspoc marks paths P by adding {path} attributes to each node located on P.
{path} is used only on linear parts of P. Cyclic parts use other mechanisms.

If P starts with some linear part and if the cyclic part can't be passed because of pathrestrictions,
then path_walk shows message "Error: No valid path" and aborts this walk.

If different paths Q and P with identical destination D share at least one node of linear part of P, then path_mark finds attribute {path} set for D and erroneously thinks, that D is reachable.
This leads to inherited warnings "Use of uninitialized value".

Test case

network:n1 = { ip = 10.1.1.0/24; }
network:n2 = { ip = 10.1.2.0/24; }

router:r1 = {
 managed;
 model = IOS, FW;
 interface:n1 = { ip = 10.1.1.1; hardware = E1; }
 interface:n2 = { ip = 10.1.2.1; hardware = E2; }
 interface:t1 = { ip = 10.9.1.1; hardware = E0; }
}
network:t1 =  { ip = 10.9.1.0/24; }

router:r2 = {
 managed;
 model = IOS, FW;
 routing = manual;
 interface:t1 = { ip = 10.9.1.2; hardware = E1; }
 interface:t2 = { ip = 10.9.2.3; hardware = E2; }
}
network:t2 =  { ip = 10.9.2.0/24; }

router:filter1 = {
 managed;
 model = ASA;
 routing = manual;
 interface:t2 = { ip = 10.9.2.1; hardware = Vlan20; }
 interface:t3 = { ip = 10.5.6.1; hardware = G0/1; 
 }
}
router:filter2 = {
 managed;
 model = IOS;
 routing = manual;
 interface:t2 = { ip = 10.9.2.2; hardware = Vlan20; }
 interface:t3 = { ip = 10.5.6.2; hardware = G0/1;  }
}
network:t3 = { ip = 10.5.6.0/24; }

router:Kunde = {
 managed;
 model = IOS;
 routing = manual;
 interface:t3 = { ip = 10.5.6.70; hardware = E0; }
 interface:n3 = { ip = 10.1.3.1; hardware = E1; }
}
network:n3 = { ip = 10.1.3.0/24; }

pathrestriction:restrict1 = 
 interface:filter1.t2,
 interface:Kunde.t3,
;
pathrestriction:restrict2 = 
 interface:filter2.t2,
 interface:Kunde.t3,
;

service:test = {
 user = network:n1, network:n2;
 permit src = user; dst = interface:Kunde.n3; prt = tcp 80;
}

Inherit nat attribute from network to subnet in same zone

If network S is subnet of network N and both are located inside the same security zone, we assume that S is part of N.
Currently attribute 'owner' of N is inherited to S.
But attribute 'nat' of network N isn't inherited to S.
This is inconsistent.

This is a bit difficult to change, because the subnet relation is only known after find_subnets_in_zone is called, which currently also checks NAT information.

Must not use routing=manual at single interface

Netspoc generiert statische Routen für Router.
Die Routen können über unterschiedliche Interfaces führen.
Das Approve gleicht die Routen auf dem Gerät an die von Netspoc generierten Routen an.
Wenn Netspoc für ein Gerät keine Routen generiert hat, dann lässt Approve die (manuell eingetragenen) Routen auf dem Gerät unverändert.

Problem:
Wir können mit routing=manual das Generieren von Routen für einzelne Interfaces abschalten.
Wenn Netspoc aber für andere Interfaces Routen generiert, dann enthält die generierte Router-Konfiguration Routen. Das Approve nimmt das als Aufforderung, alle Routen abzugleichen.
Für die Interfaces mit routing=manual werden dann fälschlich die Routen entfernt.

Lösungsansätze:
1.
Dem Approve mitteilen, dass Routen für einzelne Interfaces nicht angefasst werden sollen.
Auf Cisco-ASA enthalten die Befehle für statische Routen den Namen des Interface. Hier könnten diese Routen einfach ausgelassen werden.
Aber bei allen anderen Geräten kann nicht direkt erkannt werden, über welches Interface eine Route verläuft.
Daher weiß das Approve nicht, welche Routen es anfassen darf und welche nicht.
Dieser Ansatz kann also nicht genommen werden.
2.
routing=manual nicht mehr für einzelne Interfaces, sondern nur noch für das ganze Gerät und damit alle Interfaces zulassen. Dann tritt das Problem nicht mehr auf.

Ansatz 2 kann aber nicht direkt umgesetzt werden.
Denn wir verwenden routing=manual zur Zeit auch, wenn auf einem Interface die Routen durch ein nicht näher beschriebenes Routing-Protokoll (z.B. BGP) dynamisch gesetzt werden.
Hier ist es durchaus sinnvoll, nur an dem einen Interface das Generieren statischer Routen auszuschalten.
Sollten wir für diese Situation ein neues Schlüsselwort routing=dynamic einführen?
Technisch bedeutet routing=manual und routing=dynamic exakt dasselbe, nämlich das Netspoc für das Interface keine statischen Routen generiert.

Hilft dem Benutzer diese Unterscheidung?

Bridged device: check for multiple layer-3 interfaces

A bridged device currently can have only one layer-3 interface.
If a layer-3 interface with two ip addresses is defined, this currently fails, because internally the interface is converted into two interfaces.

interface:N = { ip = 1.2.3.4, 1.2.3.5; hardware = device; }
interface:N/left = { hardware = inside; }

At least the error message should be better:

Error: Referencing undefined network:N from interface:router.N.2

Inconsistent subnet relation with NAT

This example isn't handled correctly:

network:n1 = {
 ip = 10.1.1.0/24; 
 nat:N = { ip = 10.9.9.0/24; } 
}
network:n1_sub = {
 ip = 10.1.1.64/26; 
 nat:N = { ip = 10.8.8.64/26; } 
 subnet_of = network:n1;
}
router:u = {
 interface:n1;
 interface:n1_sub;
}

router:asa1 = {
 managed;
 model = ASA;
 routing = manual;
 interface:n1_sub = { ip = 10.1.1.65; hardware = n1; }
 interface:n2 = { ip = 10.1.2.1; hardware = n2; bind_nat = N; }
}

network:n2 = { ip = 10.1.2.0/24; }

service:s1 = {
    user = network:n1_sub;
    permit src = network:n2; dst = user; prt = tcp 80;
}
service:s2 = {
    user = network:n1;
    permit src = network:n2; dst = user; prt = tcp 80;
}

Currently we get a

Warning: Redundant rules in service:s1 compared to service:s2:
  permit src=network:n2; dst=network:n1_sub; prt=tcp 80; of service:s1
< permit src=network:n2; dst=network:n1; prt=tcp 80; of service:s2

but this isn't correct, because n1_sub isn't redundant.
We should reject this as ambiguous subnet relation from NAT instead.

Optimize external aggregate rule at managed=local

This topology
any1--r1--n2--r2--dst
with

  • r2 is
    • managed=local
    • filter_only 10.2.0.0/16
  • any1 containing only networks from 10.1.0.0/16

with this rule
permit any1 -> dst
currently would

  1. generate an ACL „permit any dst“ at r2
  2. show a warning „Missing rule for supernet rule“

To suppress this warning, an additional rule
permit any:[n2] -> dst
has currently to be defined.

This case should be optimized by netspoc.

  • it should recognize, that any1 doesn’t contain any networks from 10.2.0.0/16
  • hence, the rule is non local traffic at r2
  • hence, no ACL has to be generated at r2
  • hence, no additional rule has to be defined to suppress the warning

IP is erroneously reused in other rule

Netspoc combines similar rules by using object-groups.
Inside object-groups, adjacent IP networks are combined into larger IP networks.

The current implementation has an error.
When combining networks of one group, this may affect some similar but unrelated other group, such that the combined network erroneously occurs inside the unrelated group.

Test case:

network:n1 = { ip = 10.1.1.0/24; }
network:n2 = { ip = 10.1.2.0/24; }
network:n3 = { ip = 10.1.3.0/24; }

router:u = {
 interface:n1;
 interface:n2;
 interface:n3 = { ip = 10.1.3.1; }
}

router:r1 = {
 managed;
 model = ASA;
 interface:n3 = { ip = 10.1.3.2; hardware = n3; }
 interface:n4 = { ip = 10.1.4.1; hardware = n4; }
}

network:n4 = {
 ip = 10.1.4.0/24;
 host:h1 = { ip = 10.1.4.10; }
 host:h2 = { ip = 10.1.4.12; }
}

group:g1 = network:n1, network:n2;

service:s1 = {
 user = group:g1, network:n3;
 permit src = user; dst = host:h1; prt = tcp 80;
}
service:s2 = {
 user = group:g1;
 permit src = user; dst = host:h2; prt = tcp 80;
}

Result:

object-group network g0
 network-object 10.1.1.0 255.255.255.0
 network-object 10.1.2.0 255.255.254.0
object-group network g1
 network-object host 10.1.4.10
 network-object host 10.1.4.12
access-list n3_in extended permit tcp object-group g0 object-group g1 eq 80
access-list n3_in extended deny ip any any
access-group n3_in in interface n3

The generated access-list permits 10.1.3.0/24 for both destinations, although this must only be permitted for 10.1.4.10

Add config option "need_policy_distribution_point"

If option "need_policy_distribution_point" is set, all managed routers must have attribute "policy_distribution_point" been defined, either directly or by inheritance.
Netspoc would warn or abort otherwise.

Configure log levels for different rules / devices

Ich habe noch einmal über das Problem nachgedacht, ob / wie man das Logging in Netspoc ausdrücken kann.

  • Es genügt nicht, eine Regel mit dem Log-Wunsch zu kennzeichnen,
    weil Netspoc dann nicht weiß, für welches Gerät die Log-ACLs generiert werden sollen.
    Man möchte man ja das Logging nicht auf jedem Gerät haben; insbesondere sollen ja nicht mehrere Geräte loggen, wenn die Regel mehrere Geräte betrifft und wir wollen das Logging auch nicht auf Geräten im Landesnetz aktivieren.
  • Es genügt nicht, das Logging generell auf einem Gerät zu aktivieren, denn wir wollen das Logging ja nicht für alle Regel auf dem Gerät.

Ein zweistufiger Ansatz kann hier Erfolg versprechen:

  1. Markiere Regeln von Diensten mit log = <name>
  2. Markiere Geräte mit log:<name> = <severity>

Beide Markierungen allein bewirken noch nichts.
Aber wenn eine markierte Regel auf ein ebenso markiertes Gerät verteilt wird, dann wird das Logging aktiv.

Beispiel:

service:Notfallzugriff = {
 user = …;
 permit src = user; dst = …; prt = tcp 3389; log = Notfall;
}
router:r = {
 managed;
 log:Notfall = warning;
 …
}

Neben den Severities debug bis emergency kann ich mir zusätzlich noch das Schlüsselwort none vorstellen.
Damit kann das Logging auf ASAs für markierte Regeln ganz ausgeschaltet werden.

  • An einem Gerät können verschiedene Log-Definitionen stehen, damit unterschiedliche Regeln mit unterschiedlicher Severity geloggt werden.
  • Die gleiche Log-Definition kann auch an verschiedenen Geräten stehen, damit die gleiche Regel an verschiedenen Geräten geloggt wird.
  • An einer Regel können mehrere durch Komma getrennte Log-Markierungen gesetzt werden, damit diese Regel an verschiedenen Geräten geloggt wird.

access-list logging currently only works for ASA

Generated code for ACL logging is currently log <severity>.
This syntax works only for devices of type ASA.
We must generate device specific code here:

  • IOS: log | log-input
  • NX-OS: log
  • other: not supported

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.