Description Language for Security Policy and Topology
Table of Contents
- A policy is a set of related rules.
- Network objects and service definitions are used in rules to
describe network traffic which can or must not pass from source to
destination.
- All rules of a single policy must refer to the same network
objects in their source or destination.
- Policies have a name which may be used for documentation or
reporting purposes.
- Have name and IP address.
- Describe the topology.
- Can be used as source and destination of rules.
- have a name
- describe properties of network traffic as they typically can be
filtered by packet filters (i.e. type of protocol, port number)
- have a name
- are used to group network objects
- are used in rules for simplified management of large numbers of
network objects.
-
have a name
- are used to group service definitions
- are used in rules
The topology is build from networks and routers. Networks and routers are
connected by interfaces.
An area denotes a part of the topology which is delimited by a set
of interfaces. Areas are used to access all networks or security domains of
some part of the topology.
A crypto definition consists of three parts:
- A definition of crypto tunnels.
- A set of rules describing which traffic has to be encrypted.
- A reference to another definition with details about the used
encryption method. Currently only IPSec is supported.
Crypto definitions are very powerful: A large number of crypto tunnels of
either a hub and spoke topology or a fully meshed topology may be defined
easily.
The topology is built from networks and routers.
A router and a network are connected by an interface.
Networks may have any number of hosts, which are located inside the
network.
Routers may be managed or unmanaged. For a managed router, NetSPoC
generates access control lists which control what traffic can pass
this router and what traffic is blocked.
The whole topology is partitioned into different security domains by
managed routers.
Special network objects called 'any' objects and 'every' objects may
be defined which denote all network objects inside a security domain.
All network objects and groups have a typed name like <type>:<name>.
<name> is build from one ore more alphanumerical characters together
with hyphen and underscore. The current locale settings are used,
i.e. accented characters are allowed for European locale settings.
<ip-adr> denotes an IP address. Currently NetSPoC handles IP v4
addresses n.n.n.n with 0 <= n <= 255
<text_to_end_of_line> is any text from current position up to end of
line.
<external_name> may contain almost any characters, but not
whitespace, no delimiters [;,=]
and no quotes
["']
.
<int> is an integer
Meta symbols in syntax definitions below:
Syntax
network:<name> = {
[ owner = <external_name>, ... ; ]
{{
ip = <ip-adr><mask>;
<network NAT definition> *
[ route_hint; ]
[ subnet_of = network:<name>; ]
<host definition> *
|
unnumbered
}}
}
with
<network NAT definition> ::=
nat:<name> = {
ip = <ip-adr>[<mask>];
[ dynamic; ]
[ subnet_of = network:<name>; ]
}
<mask> ::= {{/<prefix-lenght> | ; mask = <ip-adr> }}
<prefix-lenght> ::= {{ 0 | 1 | 2 | ... | 32 }}
- A network is described by an ip address and a mask or
- may alternatively be marked as unnumbered.
- It may contain any number of host definitions.
- Unnumbered networks must have no host definitions at all.
- If used as source or destination of a rule, the ip/mask is used
directly for generating ACLs.
- An unnumbered network must not be used in rules.
- All networks must be disjunct if option 'strict_subnets' is
active. Exceptions must be declared explictly:
- route_hint: This network may enclose other networks, but it must
not have host definitions.
- subnet_of: The enclosing network must be stated explicitly.
This may be useful for a large topology, where a network may easily be
redefined by mistake.
Syntax
<host definition> ::=
host:<name> = {
[ owner = <external_name>, ... ; ]
{{
ip = <ip-adr>, ... ;
|
range = <ip-adr> - <ip-adr>;
}}
<NAT definition> *
}
<NAT definition> ::=
nat:<name> = { ip = <ip-adr>; }
- A host may only be defined inside a network definition.
- It has one or more IP addresses or
- alternatively an ip address range with first address < second address
- IP addresses must match ip/mask of the surrounding network.
- If used as source or destination of a rule, one ACL entry is
generated for each IP address.
- NetSPoC tries to automatically convert successive IP addresses from one
or multiple hosts of a common network to an IP range.
- During code generation, an IP range is split into a number of
subnetworks which cover the range. One ACL entry is generated for
each subnetwork.
Syntax
<router definition> ::=
router:<name> = {
{{
managed [ = {{ full | secondary }} ] ;
model = <name>;
[ no_group_code; ]
[ no_crypto_filter; ]
<interface definition> *
|
[ model = <name>; ]
{{
<interface definition>
|
<short interface definition>
}} *
}}
}
- A router may be managed or unmanaged.
- Managed routers may be of type 'full' or of type 'secondary'. A
type 'full' is assumed, if no value is given. See secondary packet filters below for a detailed
description.
- Managed routers need to be precisely described since this
information is needed for code generation later.
- The router model is used to generate correct code for different
router models.
Currently three models are supported:
PIX
for Cisco PIX firewalls
IOS_FW
for Cisco IOS routers with state full inspection
IOS
for stateless Cisco IOS
- NetSPoC generates optimized code using object groups for PIX firewalls and
chains for iptables. Use flag
no_group_code
to disable this
optimization.
- For IOS routers from version 12.3(8)T up, a separate access-list is used
for filtering incoming traffic of crypto tunnels. Use
attribute
no_crypto_filter
to enable the old behavior where
crypto traffic is filtered by access-lists of interfaces.
- A Router may have any number of interface definitions.
- For unmanaged routers, all attributes are optional.
- An interface definition without attributes is called a "short
interface definition".
Syntax
<interface definition> ::=
interface:<name> = {
{{ ip = <ip-adr>, ... ; | unnumbered; }}
<NAT definition> *
[ <NAT binding> ]
[ <virtual interface definition> ]
[ hardware = <external_name>; ]
[ routing = {{ EIGRP | OSPF | manual }}; ]
[ managed = {{ full | secondary }}; ]
[ reroute_permit = network:<name>, ... ; ]
[ disabled ; ]
}
<NAT definition> ::=
nat:<name> = { ip = <ip-adr>; }
<NAT binding> ::=
nat = <name>;
<virtual interface definition> ::=
virtual = {
ip = <ip-adr>;
type = {{ VRRP | HSRP }};
[ id = <int>; ]
}
<short interface definition> ::=
interface:<name>;
- Interfaces have no name of their own; instead a network name is used
to indicate that the interface is linked to a network of the same
name.
- An interface may have one or more IP addresses. All of them must
match the IP/mask of the corresponding network.
- An unnumbered interface must only be linked to an unnumbered network.
- A virtual interface defines a shared IP address and type of redundancy
protocol. See Virtual interfaces for details.
- The 'hardware' attribute indicates, which hardware interface the router
belongs to. This attribute is mandatory for managed routers.
- Multiple interfaces may belong to the same hardware interface.
- A routing protocol may be activated for an interface. In this
case, generation of static routing entries is disabled for this
interface and access control lists for this interface are automatically
augmented to permit incoming packets of the routing
protocol. Currently EIGRP and OSPF are supported.
- If
routing=manual
, no routing code is generated at all. Some
other means has to be used to configure routing for this interface.
- By default, the filter level is declared for the whole router. This may be
overridden for an interface. See secondary packet
filters for details.
- For a description of attribute 'reroute_permit',
see Rerouting inside of security domains below.
- An interface may be marked as disabled.
See Disabling part of the topology below.
- For interface definitions of unmanaged routers all attributes
may be left out.
- An interface definition without any attributes is called a "short
interface definition".
- A short interface may only be used if there is no managed
interface with static routing enabled in the same network. We need
this requirement for getting all routing entries generated.
- If used as source or destination of a rule an interface is handled
like a host.
Syntax
every:<name> = {
link = {{
network:<name>;
|
router:<name>;
}}
}
- An 'every' definition is equivalent to a group of all networks of
a security domain.
- It must not be linked to a managed router.
Syntax
any:<name> = {
[ owner = <external_name>, ... ; ]
link = {{
network:<name>;
|
router:<name>;
}}
}
- An 'any' definition is used to represent all networks of a security domain.
- It must not be linked to a managed router.
- At most one 'any' object can be defined for a security domain.
- Generated ACLs use 'any' (i.e. network 0.0.0.0/0.0.0.0) to prevent
enumeration of all networks of a security domain.
- NetSPoC generates additional deny rules to prevent
intervening networks getting undesired access.
- See Handling of 'any' objects for details.
Syntax
area:<name> = {
[ owner = <external_name>, ... ; ]
[ auto_border; ]
{{
border = interface:<name>.<name>, ... ;
| anchor = network:<name>;
}}
}
Restrictions:
- Exactly one of
border
and anchor
must be
choosen.
- Only interfaces of managed routers must be given as
border
.
- Attribute
auto_border
is mandatory for anchor
.
Syntax
<network object> ::=
{{
host:<name>
| network:<name>
| interface:<name>.<name>
| interface:<name>.[auto];
| interface:<name>.[all];
| interface:[managed].[auto];
| interface:[managed].[all];
| interface:[all].[auto];
| interface:[all].[all];
| any:<name>
| any:[all];
| any:[local];
| every:<name>
| network:[area:<name>]
| any:[area:<name>]
| group:<name>
}}
- Network objects are referenced in groups or as source or destination
of rules.
- When referencing interfaces, we need to use a different syntax than
for interface definitions: the router name followed by a network name.
- Special names [auto] and [all] may be used as network part in a
reference to an interface.
- [auto] denotes "the right side" of a router to reach src or
dst in a rule.
- [all] denotes all interfaces of a router.
- Special names [managed] and [all] may be used as router part in a
reference to an interface.
- [managed] denotes an implicitly defined group of all
managed routers.
- [all] denotes an implicitly defined group of all
routers.
- any:[all] denotes an implicitly defined group of all
'any' objects, i.e. security domains. This may be used in rules to permit
or deny traffic for the whole topology.
- any:[local] may only be used as src or dst in a rule where the counterpart
is an interface. In this case, any:[local] denotes the 'any' object, which is
directly attached to this interface.
Syntax
group:<name> = <network object>, ... ;
- A group may be empty
- A group may be defined by means of other groups
Syntax
service:<name> =
{{
ip
| tcp [[<range> :] <range>]
| udp [[<range> :] <range>]
| icmp [<int_1>[/<int_2>]]
| proto <int>
}} ;
with
<range> ::= <int_1>[-<int_2>]
- tcp, udp
-
- A <range> denotes a tcp/udp port range
- A <range> consisting of only one number denotes a single
port
- An empty <range> is equivalent with the full range of all
ports 1 - 65535
- If only one <range> is given, it describes the destination
port
- If two <range>s are given, they describe source and
destination port
- 0 < <int_1> <= <int_2> <= 65535
- icmp
-
- <int_1>, <int_2> denote icmp type and code
- 0 <= <int_1>,<int_2> <= 255
- protocol
-
- <int> is a IP protocol number
- 0 < <int> <= 255
- For describing a tcp connection between client and server, only
one rule is needed with client as source. The packets back from the
destination are allowed implicitly.
- Similar to tcp connections, only one rule is needed to let udp
packets pass from source to destination and back.
- When using service "ip" in a rule, currently only packets from
source to destination are allowed. But state full packet filters let
pass answer packets for tcp connections anyway. To get a unified
handling for tcp, udp and ip for state full and stateless packet filters,
we might change this in the future, to let ip packets pass in both
directions, with only one rule.
Syntax
servicegroup:<name> = <service>, ... ;
with
<service> ::= {{ service:<name> | servicegroup:<name> }}
- A servicegroup may be empty.
- A servicegroup may be defined by means of other servicegroups.
Syntax
policy:<name> = {
[ description = <text_to_end_of_line> ]
user = <network object>, ... ;
<policy_rule> *
}
with
<policy_rule> ::=
{{ permit | deny }}
src = <policy_object>;
dst = <policy_object>;
srv = <service>, ... ;
<policy_object> ::= {{ user | <network object>, ... ; }}
- Order of rules doesn't matter.
- Deny rules override all permit rules.
- Policies give a descriptive name to a group of related rules.
- Policies are useful for documentation and reporting purposes.
- The rules of a policy must be related in that they all use the same source
or destination object(s). This is enforced by the keyword "user" which
must be used either as src or dst or both parts of a rule.
Syntax
pathrestriction:<name> =
[ description = <text_to_end_of_line> ]
interface:<name>.<name>, ... ;
- Path restrictions are used to restrict paths inside cyclic
subgraphs of the topology.
- All paths running through two or more interfaces belonging to the
same path restriction are discarded i. e. marked as invalid.
- Only interfaces of managed routers may be referenced.
- Path restrictions must not be used to discard all paths
between some source / destination pair. Use a policy with deny rules instead.
Syntax
nat:<name> = {
ip = <ip-adr><mask>;
dynamic;
[ subnet_of = network:<name>; ]
}
with <mask>
defined as
above.
A global NAT definition may be used as a shortcut for applying multiple
identical dynamic NAT definitions to all networks in some area. See network address translation for details.
Network address translation occurs at routers.
At one side of a router, a network object is visible with its original
IP address; at another side of the router this address is translated
to another address.
Currently, NetSPoC supports static and dynamic NAT for whole
networks.
For static NAT, the translated address uses the same netmask as the
original network. The translation is automatically applied to all host and
interface definitions of the translated network. A separate NAT
definition for hosts or interfaces is not possible in this case.
For dynamic NAT, the translated address may use a different netmask than
the original network. Typically a smaller network is used for translation. IP
addresses are translated dynamically, hence hosts and interfaces of this
network are not visible from outside. But a dynamic translation of a network
may be augmented with static translations for single hosts or interfaces of
this network.
Syntax for NAT is divided into two parts:
- A NAT definition denominates the alternate IP address of an
network object.
- A NAT binding applies a set of NAT definitions to an
interface.
Network "extern" has bad IP addresses, which are not usable at network
"intern". At router "r_ext" static NAT occurs. The NAT definition and
NAT binding tells NetSPoC, that and where NAT occurs.
Hosts "extern_www" and "extern_mail" are visible with addresses
10.7.128.10 and 10.7.128.25 from "intern".
network:extern = {
ip = 128.1.2.0; mask = 255.255.255.0;
# static NAT definition
nat:bad128 = { ip = 10.7.128.0; }
host:extern_www = { ip = 128.1.2.10; }
host:extern_mail = { ip = 128.1.2.25; }
}
router:r_ext = {
interface:extern;
interface:intern = {
ip = 10.1.1.1;
# NAT binding
nat = bad128;
}
}
network:intern = { ip = 10.1.1.0; mask = 255.255.255.0; }
All NAT definitions with the same name establish a set of NAT
definitions. A set of NAT definition is effective behind
that interface where the NAT binding with the same name occurs. We are
defining behind an interface as that part of the topology
which is seen when looking from the router to that interface.
Multiple NAT definitions may be given for a single network. These are bound
to different interfaces to make different NAT definitions effective at
different parts of the topology.
For dynamic NAT, multiple networks may use identical NAT definitions. This
is used to masquerade multiple networks to a single address space.
A global NAT definition may be used as a shortcut for applying multiple
identical dynamic NAT definitions to all networks located before that
interface where the NAT binding with this name occurs.
NetSPoC needs to know about NAT for different reasons:
- When generating ACLs for an interface it must use those IP
addresses which are visible in the area of this interface.
- The same is true when generating static routing entries.
- For some types of devices NetSPoC is able to actually generate the
NAT translation rules. This is currently true for PIX firewalls.
In a given topology we may get chains of managed packet filters
on the path from src to dst. Each packet filter is a "full" packet
filter by default, which does full filtering for each rule
again and again.
A secondary packet filter has simpler rules for permitted traffic
which gets further filtering by a full packet filter. In this
case it allows any IP packets from the src network to the dst network.
This simple filtering assures that the traffic comes from the right
src and goes to the right dst.
A secondary packet filter is declared with attribute
"managed = secondary". This may be useful if a router has not
enough memory for storing a complete set of filter rules and most of
the packets get fully filtered already by some other managed device.
The filter level of each interface may be individually changed from the
default value declared for the whole router using attribute "managed" with
value "secondary" or "full".
Static and dynamic routing
From its knowledge about the topology, NetSPoC generates static
routing entries for each managed device. If an interface of a device
has an attribute "routing=<routing protocol>", no static routing
entries are generated for networks behind that interface.
Routing entries are only generated for network objects, which are
used in some rule. I.e. no routing entries are generated for unused
parts of the topology. Even for network objects which are only used as
source of a rule, routing entries are generated, since stateful packet
filters implicitly allow answer packets back to the source. If an
'any' object is used in a rule, routing entries for all networks part
of this 'any' object are generated.
Default route
A default route may be defined for a topology by placing a network
with IP address and mask equal 0.0.0.0. Such a network must have an
attribute "route_hint".
Alternatively, NetSPoC can automatically define a default route for
each managed device as a means to reduce the number of static routing
entries.
- At each managed device, a default route is automatically inserted such
that it replaces the maximum number of routing entries.
- This behavior may be switched on or off by option --auto_default_route.
- This option must be switched off, if a user defined default route is
given.
- This behavior is automatically disabled for routers where at least one
interface has dynamic routing enabled.
Optimization
Multiple routing entries for networks which are in a subnet
relation, are replaced by a single routing entry.
Internal traffic which flows inside a security domain isn't
filtered at all. Sometimes an interface X of a managed (filtering)
router is used as a default route for traffic which normally flows
inside a security domain. This would cause internal traffic to be
routed to X, which would deny this traffic.
NetSPoC is prepared to handle this case by defining an attribute
'reroute_permit' for a managed interface. Value of this attribute is a
list of networks, for which any internal traffic should be allowed.
Example
router:x is managed, router:y is unmanaged.
router:x -- network:a -- router:y -- network:b
network:a and network:b are inside one security domain, since
router:y isn't managed. If traffic from network:a to network:b is
routed via router:x and router:y, router:x would deny this traffic.
Use "reroute_permit = network:b" at "interface:x.a" to permit any
incoming traffic to network:b.
A virtual interface defines a shared IP address and type of redundancy
protocol at two or more interfaces. Currently, redundancy protocols VRRP and
HSRP are supported.
- The virtual IP address is used as destination when generating static
routes.
- Access control lists for the associated real interfaces are automatically
augmented to permit incoming packets of the redundancy protocol.
- At least two interfaces with the same virtual IP are needed.
- The set of interfaces with same virtual IP
- must be linked to the same network and
- must be part of the same cyclic subgraph.
- A virtual IP must be different from normal IP address(es).
- The 'id' attribute is optional. It is used for consistency checks but
currently not used when generating code for managed devices.
An interface may be explicitly marked as disabled. This implicitly
marks all network objects as disabled, that are located behind
this interface. We are defining behind an interface as that
part of the topology which is seen when looking from the router to
that interface. All occurrences of disabled network objects in groups and
rules are silently discarded.
crypto:<name> = {
[ description = <text_to_end_of_line> ]
type = ipsec:<name>;
[ hub = <network object>, ... ;
spoke = <network object>, ... ;
]
mesh = <network object>, ... ; *
<crypto_rule> *
}
with
<crypto_rule> ::=
{{ permit | deny }}
src = <network object>, ... ;
dst = <network object>, ... ;
srv = <service>, ... ;
ipsec:<name> = {
key_exchange = isakmp:<name>;
esp_encryption = {{ aes | aes192 | des | 3des | none }};
esp_authentication = {{ md5_hmac | sha_hmac | none }};
ah = {{ md5_hmac | sha_hmac | none }};
pfs_group = {{ 1 | 2 | 5 }};
lifetime = <number> <timeunit>;
}
isakmp:<name> = {
identity = {{ address | fqdn }};
nat_traversal = {{ on | off }};
authentication = {{ preshare | rsasig }};
encryption = {{ aes | aes192 | des | 3des }};
hash = {{ md5 | sha }};
group = {{ 1 | 2 | 5 }};
lifetime = <number> <timeunit>;
}
with
<timeunit> ::=
{{ sec | min | hour | day | secs | mins | hours | days }};
The meaning of 'any' is different in a NetSPoC rule from that in an ACL.
For NetSPoC, any:X means "any network object of the security domain
where any:X is located".
For an ACL which filters incoming traffic of an interface, any
(i.e. 0.0.0.0/0.0.0.0) means "any network object beyond the interface
where the ACL is applied to".
-
as source:
- any data object connected directly or indirectly with
this interface.
-
as destination:
- any data object located behind the router where the
interface belongs to.
PIX firewalls have a security level associated with each interface.
We don't want to expand our syntax to state them explicitly,
but instead we try to derive the level from the interface name:
- Interface 'inside' gets level 100
- Interface 'outside' gets level 0
- For each other interface there must be a number at the end of its
name which is taken as the relative security level.
I.e 'DMZ-slot:4'
< 'DMZ-slot:5'
It is not necessary the find the exact level; what we need to know
is the relation of the security levels to each other.
Fully implemented, but documentation has to be done ...
- Access control lists
- Routing
- NAT commands for some devices
- PIX
- access-list (conduit and outbound are not supported)
- object-group
- icmp, telnet, ssh, http
- route
- Cisco IOS with firewall feature set
- ip access-list extended
- ip route
- Cisco IOS without firewall feature set
- ip access-list extended (rules for answer packets are added automatically)
- ip route
- Linux
Copyright (c) 2005, Heinz Knutzen
heinzknutzen@users.berlios.de