NFV Services Tutorial¶
This tutorial will cover using faucet with Network Function Virtualisation (NFV) services.
NFV services that will be demonstrated in this tutorial are:
- DHCP server
- NAT Gateway
- BRO Intrusion Detection System (IDS)
This tutorial demonstrates how the previous topics in this tutorial series can be integrated with other services on our network.
Prerequisites¶
- A good understanding of the previous tutorial topics (ACL tutorial, VLAN Tutorial, Routing Tutorial)
- Install Faucet - Package installation steps 1 & 2
- Install Open vSwitch - Connect your first datapath steps 1 & 2
- Useful Bash Functions - Copy and paste the following definitions into your bash terminal, or to make them persistent between sessions add them to the bottom of your .bashrc and run ‘source .bashrc’.
create_ns () {
NETNS=$1
IP=$2
sudo ip netns add ${NETNS}
sudo ip link add dev veth-${NETNS} type veth peer name veth0 netns $NETNS
sudo ip link set dev veth-${NETNS} up
sudo ip netns exec $NETNS ip link set dev veth0 up
sudo ip netns exec $NETNS ip addr add dev veth0 $IP
sudo ip netns exec $NETNS ip link set dev lo up
}
as_ns () {
NETNS=$1
shift
sudo ip netns exec $NETNS $@
}
cleanup () {
for br in $(sudo ovs-vsctl list-br); do
sudo ovs-vsctl del-br $br
done
IFS=$'\n';
for i in $(sudo ip netns list); do
NS=$(echo $i | cut -d ' ' -f1)
sudo ip netns delete $NS;
# Sometimes the veth-$NS is not deleted.
sudo ip link delete veth-$NS;
done
}
add_tagged_dev_ns () {
NETNS=$1
IP=$2
VLAN=$3
sudo ip netns exec $NETNS ip link add link veth0 name veth0.${VLAN} type vlan id $VLAN
sudo ip netns exec $NETNS ip link set dev veth0.${VLAN} up
sudo ip netns exec $NETNS ip addr flush dev veth0
sudo ip netns exec $NETNS ip addr add dev veth0.${VLAN} $IP
}
clear_ns(){
NETNS=$1
sudo ip netns delete $NETNS
sudo ovs-vsctl del-port br0 veth-${NETNS}
}
Let’s start by run the cleanup script to remove old namespaces and switches.
cleanup
Network setup¶
We will create a switch and attach seven hosts like so:
The network will be divided into 3 VLANs like so, 2 client vlans (200 & 300) with two clients each (host4-7), and a VLAN for the Bro server. The layer 2 & 3 diagram looks like:
# BRO
create_ns host1 192.168.0.1/24
# DHCP server
create_ns host2 0
add_tagged_dev_ns host2 192.168.2.2/24 200 # to serve vlan 200
add_tagged_dev_ns host2 192.168.3.2/24 300 # to serve vlan 300
# Gateway
create_ns host3 0
add_tagged_dev_ns host3 192.168.2.3/24 200 # to serve vlan 200
add_tagged_dev_ns host3 192.168.3.3/24 300 # to serve vlan 200
# vlan 200 hosts
create_ns host4 0
create_ns host5 0
# vlan 300 hosts
create_ns host6 0
create_ns host7 0
Then create an OpenvSwitch and connect all hosts to it.
sudo ovs-vsctl add-br br0 \
-- set bridge br0 other-config:datapath-id=0000000000000001 \
-- set bridge br0 other-config:disable-in-band=true \
-- set bridge br0 fail_mode=secure \
-- add-port br0 veth-host1 -- set interface veth-host1 ofport_request=1 \
-- add-port br0 veth-host2 -- set interface veth-host2 ofport_request=2 \
-- add-port br0 veth-host3 -- set interface veth-host3 ofport_request=3 \
-- add-port br0 veth-host4 -- set interface veth-host4 ofport_request=4 \
-- add-port br0 veth-host5 -- set interface veth-host5 ofport_request=5 \
-- add-port br0 veth-host6 -- set interface veth-host6 ofport_request=6 \
-- add-port br0 veth-host7 -- set interface veth-host7 ofport_request=7 \
-- set-controller br0 tcp:127.0.0.1:6653 tcp:127.0.0.1:6654
DHCP Server¶
We will use dnsmasq as our DHCP server.
First install dnsmasq:
sudo apt-get install dnsmasq
Let’s run two services one for vlan 200 and another for vlan 300 as following
# 192.168.2.0/24 for vlan 200
as_ns host2 dnsmasq --no-ping -p 0 -k \
--dhcp-range=192.168.2.10,192.168.2.20 \
--dhcp-sequential-ip \
--dhcp-option=option:router,192.168.2.3 \
-O option:dns-server,8.8.8.8 \
-I lo -z -l /tmp/nfv-dhcp-vlan200.leases \
-8 /tmp/nfv.dhcp-vlan200.log -i veth0.200 --conf-file= &
# 192.168.3.0/24 for vlan 300
as_ns host2 dnsmasq --no-ping -p 0 -k \
--dhcp-range=192.168.3.10,192.168.3.20 \
--dhcp-sequential-ip \
--dhcp-option=option:router,192.168.3.3 \
-O option:dns-server,8.8.8.8 \
-I lo -z -l /tmp/nfv-dhcp-vlan300.leases \
-8 /tmp/nfv.dhcp-vlan300.log -i veth0.300 --conf-file= &
Now let’s configure faucet yaml file (/etc/faucet/faucet.yaml)
vlans:
bro-vlan:
vid: 100
description: "bro network"
vlan200:
vid: 200
description: "192.168.2.0/24 network"
vlan300:
vid: 300
description: "192.168.3.0/24 network"
dps:
sw1:
dp_id: 0x1
hardware: "Open vSwitch"
interfaces:
1:
name: "host1"
description: "BRO network namespace"
native_vlan: bro-vlan
2:
name: "host2"
description: "DHCP server network namespace"
tagged_vlans: [vlan200, vlan300]
3:
name: "host3"
description: "gateway network namespace"
tagged_vlans: [vlan200, vlan300]
4:
name: "host4"
description: "host4 network namespace"
native_vlan: vlan200
5:
name: "host5"
description: "host5 network namespace"
native_vlan: vlan200
6:
name: "host6"
description: "host6 network namespace"
native_vlan: vlan300
7:
name: "host7"
description: "host7 network namespace"
native_vlan: vlan300
Now reload faucet configuration file.
sudo systemctl reload faucet
Use dhclient to configure host4 to host7 using DHCP (it may take a few seconds, but should return when successful).
as_ns host4 dhclient veth0
as_ns host5 dhclient veth0
as_ns host6 dhclient veth0
as_ns host7 dhclient veth0
You can check /tmp/nfv-dhcp<vlanid>.leases and /tmp/nfv.dhcp<vlanid>.log to find their IPs. e.g. file /tmp/nfv-dhcp-vlan300.leases
1525938604 7e:bb:f0:46:6a:e8 192.168.3.11 ubuntu *
1525938567 76:58:6c:26:78:44 192.168.3.10 * *
Alternatively:
as_ns host4 ip addr show
as_ns host5 ip addr show
as_ns host6 ip addr show
as_ns host7 ip addr show
If the hosts have IPs then great our DHCP works,
Try to ping between them
as_ns host4 ping <ip of host5> # both in vlan200 should work
as_ns host6 ping <ip of host7> # both in vlan300 should work
as_ns host4 ping <ip of host6> # each in different vlan should not work
Ping between hosts vlan 200 and vlan 300 works because host3 (gateway) forwards the traffic by default. So we will fix this for the next sections by changing iptables on host3 to not route traffic by default.
as_ns host3 iptables -P FORWARD DROP
Now the ping should fail
as_ns host4 ping <host7 ip addr>
Gateway (NAT)¶
In this section we will configure host3 as a gateway (NAT) to provide internet connection for our network.
NS=host3 # gateway host namespace
TO_DEF=to_def # to the internet
TO_NS=to_${NS} # to gw (host3)
OUT_INTF=enp0s3 # host machine interface for internet connection.
sudo sysctl net.ipv4.ip_forward=1
as_ns ${NS} sysctl net.ipv4.ip_forward=1
sudo ip link add name ${TO_NS} type veth peer name ${TO_DEF} netns ${NS}
sudo ip addr add 192.168.100.1/30 dev ${TO_NS}
sudo ip link set ${TO_NS} up
as_ns ${NS} ip addr add 192.168.100.2/30 dev ${TO_DEF}
as_ns ${NS} ip link set ${TO_DEF} up
as_ns ${NS} ip route add default via 192.168.100.1
as_ns ${NS} iptables -P FORWARD DROP
as_ns ${NS} iptables -A FORWARD -i veth0.200 -o ${TO_DEF} -j ACCEPT
as_ns ${NS} iptables -A FORWARD -i veth0.300 -o ${TO_DEF} -j ACCEPT
as_ns ${NS} iptables -A FORWARD -i ${TO_DEF} -o veth0.200 -j ACCEPT
as_ns ${NS} iptables -A FORWARD -i ${TO_DEF} -o veth0.300 -j ACCEPT
as_ns ${NS} iptables -t nat -F
as_ns ${NS} iptables -t nat -A POSTROUTING -o ${TO_DEF} -j MASQUERADE
sudo iptables -P FORWARD DROP
sudo iptables -F FORWARD
sudo iptables -t nat -F
sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/30 -o ${OUT_INTF} -j MASQUERADE
sudo iptables -A FORWARD -i ${OUT_INTF} -o ${TO_NS} -j ACCEPT
sudo iptables -A FORWARD -i ${TO_NS} -o ${OUT_INTF} -j ACCEPT
Now try to ping google.com from any host, it should work as the gateway and DNS is now configured.
as_ns host4 ping www.google.com
as_ns host7 ping www.google.com
BRO IDS¶
BRO installation¶
We need first to install bro. We will use the binary package version 2.5.3 for this test.
sudo apt-get install bro broctl
Configure BRO¶
In /etc/bro/node.cfg, set veth0 as the interface to monitor
[bro]
type=standalone
host=localhost
interface=veth0
Comment out MailTo in /etc/bro/broctl.cfg
# Recipient address for all emails sent out by Bro and BroControl.
# MailTo = root@localhost
Run bro in host2¶
Since this is the first-time use of the bro command shell application, perform an initial installation of the BroControl configuration:
as_ns host1 broctl install
Then start bro instant
as_ns host1 broctl start
Check bro status
as_ns host1 broctl status
Name Type Host Status Pid Started
bro standalone localhost running 15052 07 May 09:03:59
Now let’s add a mirror ACL so all vlan200 & vlan300 traffic is sent to BRO.
We will use vlan acls (more about acl and vlan check vlan and acl tutorials).
acls:
mirror-acl:
- rule:
actions:
allow: true
mirror: 1
vlans:
bro-vlan:
vid: 100
description: "bro network"
vlan200:
vid: 200
description: "192.168.2.0/24 network"
acls_in: [mirror-acl]
vlan300:
vid: 300
description: "192.168.3.0/24 network"
acls_in: [mirror-acl]
dps:
sw1:
dp_id: 0x1
hardware: "Open vSwitch"
interfaces:
1:
name: "host1"
description: "BRO network namespace"
native_vlan: bro-vlan
2:
name: "host2"
description: "DHCP server network namespace"
tagged_vlans: [vlan200, vlan300]
3:
name: "host3"
description: "gateway network namespace"
tagged_vlans: [vlan200, vlan300]
4:
name: "host4"
description: "host4 network namespace"
native_vlan: vlan200
5:
name: "host5"
description: "host5 network namespace"
native_vlan: vlan200
6:
name: "host6"
description: "host6 network namespace"
native_vlan: vlan300
7:
name: "host7"
description: "host7 network namespace"
native_vlan: vlan300
As usual reload faucet configuration file.
sudo systemctl reload faucet
If we generate some DHCP traffic on either of the hosts VLANs
as_ns host4 dhclient veth0
Then if we inspect the bro logs, we should see that bro has learnt about the two DHCP Servers. If the file does not exist check that faucet has successfully reloaded, and try the dhclient command again.
sudo cat /var/log/bro/current/known_services.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path known_services
#open 2018-05-10-12-09-05
#fields ts host port_num port_proto service
#types time addr port enum set[string]
1525910945.405356 192.168.3.2 67 udp DHCP
1525910975.329404 192.168.2.2 67 udp DHCP