IP packet filtering

This is where IPv4 and IPv6 packet filtering is configured. The device monitors incoming and outgoing traffic, and determines whether to allow or deny traffic, based on sequenced list of rules. Each rule contains a packet selector and the related action.

The IP packet filtering module leverages Netfilter, and re-uses its concepts.

Note

Filtering rules not configured by the management system will not be displayed by show state and will be lost when a new firewall configuration is committed.

Caution

Stateful IP packet filtering and CG-NAT are exclusive. If CG-NAT is enabled, stateful IP packet filtering must be disabled on ports bound to the fast path.

See also

The command reference for details.

Definitions

Chains

A chain is a list of rules. It is responsible for determining how an incoming, outgoing or forwarded packet should be processed by the filtering module.

There are several default chains, associated to hooks in the routing stack:

  • prerouting is called as soon as packets are received

  • input is called for locally delivered packets

  • forward is called when the packet is being routed

  • output is called for locally generated packets

  • postrouting is called when the packets are about to be sent

If a packet entering a default chain does not match any rule, it will be processed by the chain’s default policy.

User-chains can be defined as well, and called from the default chains.

Tables

Several tables are available. Each table has a specific purpose and defines some specific default chains. The chains cross the different tables in a predefined priority.

The raw table is mainly used to exempt packets from connection tracking. Only the prerouting and output chains are available in this table. It is always crossed first (before connection tracking).

The mangle table is the packet alteration table. All the default chains are available in this table. It is called before filter, and after connection tracking.

The filter table is the default table. Only the input, forward and output chains are available in this table. This is where packets are actually filtered. It is called after the mangle table.

Rules

A rule is defined by a sequence number, a packet selector and an action. It specifies what action to apply to packets that match the selector. Packets are compared to each rule until it matches one rule selector. The action is then applied to the packet and look up into the chain is stopped. If a packet does not match any of the rules in a default chain, it is applied the default policy.

Groups

A group is a set of IP addresses or networks. The rule packet selector can reference a group as source or destination.

Connection tracking

To perform stateful filtering or NAT, the device can monitor the connections and maintain their state, using the connection tracking module. Each connection is stored in a conntrack, defined by its source and destination address, its source and destination port in the two directions (named origin and reply), and the state of the connection.

Here is an example of a conntrack defining an SSH connection from 10.0.2.2 port 58242 to 10.0.2.15 port 22. The connection is established, meaning that packets were seen in the two directions.

tcp      6 431995 ESTABLISHED src=10.0.2.2 dst=10.0.2.15 sport=58242 dport=22 src=10.0.2.15 dst=10.0.2.2 sport=22 dport=58242 [ASSURED] mark=0 use=1

The connection tracking module is called in prerouting and output chains, after the raw table. It is enabled for all packets, unless disabled using the notrack action.

The show conntracks command displays the currently created conntracks.

vrouter> show conntracks
tcp      6 431995 ESTABLISHED src=10.0.2.2 dst=10.0.2.15 sport=58242 dport=22 src=10.0.2.15 dst=10.0.2.2 sport=22 dport=58242 [ASSURED] mark=0 use=1
conntrack v1.4.5 (conntrack-tools): 1 flow entries have been shown.

Stateless filtering

Stateless filtering does not need the connection tracking module.

Let’s configure the following:

  • create a user chain named outside to store rules common to the public interfaces pub0 and pub1

  • change the input policy to drop

  • create a trusted address group containing the 2.2.2.2 and 4.4.4.4 IP addresses

  • allow all traffic from 1.1.1.1 IP address and trusted group, and only ssh and netconf connections from other IPs entering from the pub0 and pub1 interfaces

  • allow all the traffic entering from the priv interface

  • allow all the traffic entering from the lo interface (used by the cli)

vrouter running vrf main# group ipv4
vrouter running ipv4# address-group trusted
vrouter running address-group trusted# address 2.2.2.2
vrouter running address-group trusted# address 4.4.4.4
vrouter running address-group trusted# .. .. ..
vrouter running vrf main# firewall ipv4
vrouter running ipv4# filter
vrouter running filter# chain outside
vrouter running chain outside# rule 1 source address 1.1.1.1 description "allow 1.1.1.1" action accept
vrouter running chain outside# rule 2 source group trusted description "allow trusted" action accept
vrouter running chain outside# rule 3 protocol tcp destination port 22 description "allow ssh" action accept
vrouter running chain outside# rule 4 protocol tcp destination port 830 description "allow netconf" action accept
vrouter running chain outside# ..
vrouter running filter# input
vrouter running input# policy drop
vrouter running input# rule 1 inbound-interface pub0 action chain outside
vrouter running input# rule 2 inbound-interface pub1 action chain outside
vrouter running input# rule 3 inbound-interface priv action accept
vrouter running input# rule 4 inbound-interface lo description "allow local netconf traffic" action accept

Note

This configuration is partial, and only shown as an example. It should not be used as is in production.

Let’s fetch the state after committing this configuration:

vrouter running vrf main# show state group
group
    ipv4
        address-group trusted
            address 2.2.2.2
            address 4.4.4.4
            ..
        ..
    ..
vrouter running vrf main# show state firewall ipv4 filter
filter
    input
        bytes 23862
        policy drop
        packets 111
        rule 1 counters bytes 0 packets 0 inbound-interface pub0 action chain outside
        rule 2 counters bytes 0 packets 0 inbound-interface pub1 action chain outside
        rule 3 counters bytes 0 packets 0 inbound-interface priv action accept
        rule 4 description "allow local netconf traffic" counters bytes 803700 packets 2289 inbound-interface lo action accept
        ..
    forward
        bytes 0
        policy accept
        packets 0
        ..
    output
        bytes 811590
        policy accept
        packets 2400
        ..
    chain outside
        bytes 0
        packets 0
        rule 1 description "allow 1.1.1.1" counters bytes 0 packets 0 source address 1.1.1.1/32 action accept
        rule 2 description "allow trusted" counters bytes 0 packets 0 source group trusted action accept
        rule 3 description "allow ssh" counters bytes 0 packets 0 protocol tcp destination port 22 action accept
        rule 4 description "allow netconf" counters bytes 0 packets 0 protocol tcp destination port 830 action accept
        ..
    ..

The same configuration can be made using this NETCONF XML configuration:

vrouter> show config xml absolute vrf main group
<config xmlns="urn:6wind:vrouter">
  <vrf>
    <name>main</name>
    <group xmlns="urn:6wind:vrouter/group">
      <ipv4>
        <address-group>
          <name>trusted</name>
          <address>2.2.2.2</address>
          <address>4.4.4.4</address>
        </address-group>
      </ipv4>
    </group>
  </vrf>
</config>

vrouter> show config xml absolute vrf main firewall
<config xmlns="urn:6wind:vrouter">
  <vrf>
    <name>main</name>
    <firewall xmlns="urn:6wind:vrouter/firewall">
      <ipv4>
        <filter>
          <forward>
            <policy>accept</policy>
          </forward>
          <output>
            <policy>accept</policy>
          </output>
          <input>
            <policy>drop</policy>
            <rule>
              <id>1</id>
              <inbound-interface>
                <name>pub0</name>
              </inbound-interface>
              <action>
                <chain>outside</chain>
              </action>
            </rule>
            <rule>
              <id>2</id>
              <inbound-interface>
                <name>pub1</name>
              </inbound-interface>
              <action>
                <chain>outside</chain>
              </action>
            </rule>
            <rule>
              <id>3</id>
              <inbound-interface>
                <name>priv</name>
              </inbound-interface>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
            <rule>
              <id>4</id>
              <inbound-interface>
                <name>lo</name>
              </inbound-interface>
              <description>allow local netconf traffic</description>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
          </input>
          <chain>
            <name>outside</name>
            <policy>accept</policy>
            <rule>
              <id>1</id>
              <source>
                <address>
                  <value>1.1.1.1</value>
                </address>
              </source>
              <description>allow 1.1.1.1</description>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
            <rule>
              <id>2</id>
              <source>
                <group>
                  <value>trusted</value>
                </group>
              </source>
              <description>allow trusted</description>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
            <rule>
              <id>3</id>
              <protocol>
                <value>tcp</value>
              </protocol>
              <destination>
                <port>
                  <value>22</value>
                </port>
              </destination>
              <description>allow ssh</description>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
            <rule>
              <id>4</id>
              <protocol>
                <value>tcp</value>
              </protocol>
              <destination>
                <port>
                  <value>830</value>
                </port>
              </destination>
              <description>allow netconf</description>
              <action>
                <standard>accept</standard>
              </action>
            </rule>
          </chain>
        </filter>
      </ipv4>
    </firewall>
  </vrf>
</config>

Stateful filtering

Using the connection tracking, it is possible to match packets that are part of an existing connection.

The following configuration adds to the previous stateless configuration some stateful filtering rules, by allowing packets from an existing connection, but denying packets for a new one.

vrouter running vrf main# firewall ipv4
vrouter running ipv4# filter
vrouter running filter# chain outside
vrouter running chain outside# rule 5 conntrack state established related description "accept established and related connections" action accept
vrouter running chain outside# rule 6 conntrack state new description "deny new connections" action drop
vrouter running chain outside# commit