+
+
+
+
+
+ Ansible KVM Router Lab Part 5
+
+ date: 2021-10-17
+Introduction
+This is Part 5 of a multi-part series of blog posts for building a
+router lab
+automatically using a series of bash scripts and ansible.
+Ansible KVM Router Lab Part 1
+is an overview.
+In Ansible KVM Router Lab Part 2,
+I break down the script
+build_vms.bash.
+In Ansible KVM Router Lab Part 3,
+I explain
+define_bridge_networks.bash
+and
+shutdown_vms.bash
+scripts which are used to construct the lab.
+In Ansible KVM Router Lab Part 4,
+I explain
+connect_vms_to_bridges.bash,
+start_vms.bash,
+and rebuild_known_hosts.bash
+scripts which are used to construct the lab.
+In this post I explain how I use Ansible to finish constructing the lab.
+In Ansible KVM Router Lab Part 6,
+I explain
+disconnect_vms_from_bridges.bash,
+undefine_and_remove_vms.bash,
+and remove_bridge_networks
+which are used to destroy the lab.
+Setup Ansible
+
+- Configure ansible host file
+
# ~/.ansible.cfg
+[defaults]
+inventory = ~/router-lab/ansible/hosts.yml
+
+- Setup bashrc
+
# ~/.bashrc
+export LIBVIRT_DEFAULT_URI="qemu+ssh://<user>@<server>/system"
+
+alias ansible-pb=anspb
+anspb() {
+ ANS_DIR=~/router-lab/ansible/playbooks;
+ echo Changing to "${ANS_DIR}" and executing: ansible-playbook "${@}"
+ (cd $ANS_DIR || exit ; ansible-playbook "${@}")
+}
+
+- install apps
+
apt install ansible ansible-lint
+
+
+Run Ansible
+ansible-pb build_out_routers.yml -K
+
+or if you want to first update all the clients
+ansible-pb update_and_build.yml -K
+
+Ansible Tasks
+This is an explaination of the tasks in the Ansible Playbook.
+Playbooks are executed from top to bottom.
+Install dnsmasq
, iptables-persistent
+This task is only run against the first and second lab clients as
+they are the routers.
+Install traceroute
+Traceroute is parsed in a later task to confirm that traffic is
+following the correct route.
+(Also incidentally installs needrestart
and screen
.)
+Backup /etc/network/interfaces
+This is a simple bash command that tests if /etc/network/interfaces.bak
+exists, and if not creates it.
+Update Network Config
+This task updates /etc/network/interfaces
in all the lab clients
+to describe the network interfaces needed to connect to each other.
+For instance, here is the new /etc/network/interfaces
file for dnettwo.
+
# /etc/network/interfaces
+# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+source /etc/network/interfaces.d/*
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+# The primary network interface
+allow-hotplug enp1s0
+iface enp1s0 inet dhcp
+
+# The primary network interface
+allow-hotplug enp7s0
+iface enp7s0 inet dhcp
+
+auto enp8s0
+iface enp8s0 inet static
+ address 10.4.4.1
+ network 10.4.4.0
+ netmask 255.255.255.0
+ broadcast 10.4.4.255
+
+Backup /etc/dnsmasq.conf
+This is a simple bash command that tests if /etc/dnsmasq.conf.bak
+exists, and if not creates it. (only applies to the two router clients)
+
+This task copies the templates for /etc/dnsmasq.conf
to each of
+the two router clients.
+dnsmasq
is used to provide DHCP (and name resolution).
+For instance, here is the new /etc/dnsmasq.conf
for dnetone.
+
# /etc/dnsmasq.conf
+dhcp-range=10.5.5.50,10.5.5.150
+listen-address=127.0.0.1, 10.5.5.1
+
+
+This applies to all the lab clients except for the first one,
+changes the default route. A bash script is copied from
+template to /etc/network/if-up.d/ifup-script
.
+For instance here is ifup-script
for dnetthree.
+
#!/bin/bash
+# /etc/network/if-up.d/ifup-script
+
+default_dev="$(ip route | head -1 | awk '{print $5}')"
+echo "${default_dev}"
+
+if [ "${default_dev}" == "enp1s0" ]
+then
+ ip route del default via 10.55.44.1 dev enp1s0
+fi
+
+if [ "${default_dev}" != "enp7s0" ]
+then
+ ip route add default via 10.4.4.1 dev enp7s0
+fi
+
+Restart Network and dnsmasq
+This is sequential:
+
+- enp7s0 is restarted on dnet
+dnsmasq
is restarted on dnetone, offering service on enp7s0
+- enp7s0 and enp8s0 are restarted on dnettwo, thus soliciting dhcp service on enp7s0, and triggering
/etc/network/if-up.d/ifup-script
+dnsmasq
is restarted on dnettwo, offering service on enp8s0
+- enp7s0 is restarted on dnetthree, dnetfour, and dnetfive, thus soliciting dhcp service on enp7s0, and triggering
/etc/network/if-up.d/ifup-script
+
+Backup /etc/sysctl.conf
+This is a simple bash command that tests if /etc/sysctl.conf.bak
+exists, and if not creates it. (only applies to the two router clients)
+Enable ipv4 forwarding
+This is a simple bash command that uncomments the option for ipv4 forwarding
+in /etc/sysctl.conf
, applies only to the two routers.
+
# /etc/sysctl.conf
+...
+# this
+#net.ipv4.ip_forward=1
+...
+# becomes this
+net.ipv4.ip_forward=1
+...
+
+Start ipv4 forwarding
+This simple bash command starts ipv4 forwarding, applies only
+to the two routers.
+
bash -c "sysctl -w net.ipv4.ip_forward=1"
+
+
+This applies only to the two router clients.
+From iptables
's point of view, the ansible connection isn't a RELATED INPUT
+connection, thus it is necessary to bring up a firewall in a two-step
+process that involves first ACCEPTING RELATED OUTPUT connections in a workaround.
+From ansible template, the following is copied to /dev/shm/iptables_workaround
+
# /dev/shm/iptables_workaround
+*filter
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+
+-A INPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
+-A OUTPUT -j ACCEPT -m conntrack --ctstate ESTABLISHED,RELATED
+
+COMMIT
+
+Apply iptables
workaround
+This applies only to the two router clients.
+The following command is dispatched to apply the above iptables_workaround:
+
bash -c "iptables-restore < /dev/shm/iptables_workaround"
+
+
+This applies only to the two router clients.
+From ansible template the following is copied to /etc/iptables/rules.v4
on dnetone.
+
*nat
+-A POSTROUTING -o enp1s0 -j MASQUERADE
+COMMIT
+
+*filter
+-A INPUT -i lo -j ACCEPT
+# allow ssh, so that we do not lock ourselves
+-A INPUT -i enp1s0 -p tcp -m tcp --dport 22 -j ACCEPT
+# allow incoming traffic to the outgoing connections,
+# et al for clients from the private network
+-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+# prohibit everything else incoming
+-A INPUT -i enp1s0 -j DROP
+COMMIT
+
+From ansible template the following is copied to /etc/iptables/rules.v4
on dnettwo.
+
*nat
+-A POSTROUTING -o enp7s0 -j MASQUERADE
+COMMIT
+
+*filter
+-A INPUT -i lo -j ACCEPT
+# allow ssh, so that we do not lock ourselves
+-A INPUT -i enp7s0 -p tcp -m tcp --dport 22 -j ACCEPT
+# allow incoming traffic to the outgoing connections,
+# et al for clients from the private network
+-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+# prohibit everything else incoming
+-A INPUT -i enp7s0 -j DROP
+COMMIT
+
+Apply iptables
firewall
+This applies only to the two router clients.
+The following command is dispatched to apply the above from /etc/iptables/rules.v4
:
+
bash -c "iptables-restore < /etc/iptables/rules.v4"
+
+traceroute
test
+The following script is dispatched to dnettwo:
+
#!/bin/bash
+
+RESULT="$(traceroute 8.8.8.8)"
+
+FIRST_HOP="$(echo "${RESULT}" | head -2 | tail -1 | awk '{print $2}')"
+
+if [ "${FIRST_HOP}" == "10.5.5.1" ]
+then
+ exit 0
+else
+ exit 1
+fi
+
+The following script is dispatched to dnetthree, dnetfour, and dnetfive:
+#!/bin/bash
+
+RESULT="$(traceroute 8.8.8.8)"
+
+FIRST_HOP="$(echo "${RESULT}" | head -2 | tail -1 | awk '{print $2}')"
+
+if [ "${FIRST_HOP}" != "10.4.4.1" ]
+then
+ exit 1
+fi
+
+SECOND_HOP="$(echo "${RESULT}" | head -3 | tail -1 | awk '{print $2}')"
+
+if [ "${SECOND_HOP}" == "10.5.5.1" ]
+then
+ exit 0
+else
+ exit 1
+fi
+
+To Be Continued
+In Ansible KVM Router Lab Part 6,
+I explain
+disconnect_vms_from_bridges.bash,
+undefine_and_remove_vms.bash,
+and remove_bridge_networks
+which are used to destroy the lab.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+