Proxmox Network Inside Network With Vyos 4
In part 3 we did our first bit of automation using Ansible to set up the base config for VyOS, In this part we will go over defining our networks and everything needed for a functioning network.
Step 1 - New roles
Lets add a role to define our network and a playbook to run to create them, we will also need a new
group_vars
we will use lab
as in the last part we created a group called vyos
and lab
and put
our firewall under lab
and the lab
group as a child of vyos
. Your directory should now look
like the example below with these additions.
If you want you can just grab this from my Github - blog-4 branch.
.
├── ansible.cfg
├── group_vars
│ ├── all
│ │ └── defaults.yml
│ ├── lab <-- new directory
│ │ └── networks.yml <-- new file
│ └── vyos.yml
├── hosts
├── Pipfile
├── Pipfile.lock
├── README.md
├── requirements.yml
├── roles
│ ├── vyos_base
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── base.j2
│ ├── vyos_networks <-- new role
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── networks.j2
│ └── vyos_users
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ └── users.j2
├── vars
│ └── users.yml
├── vyos_base.yml
├── vyos_networks.yml <-- new playbook
└── vyos_users.yml
Lets first take a look at the playbook, this should be familiar as its the same playbook as the others, just pointing to a different role.
---
- name: Set up VyOS Networks
hosts: vyos
gather_facts: true
order: inventory
roles:
- vyos_networks
Easy right, Now lets move on the role
again , nothing overly complecated here either, its the same
layout as the other roles in terms of tasks
and handlers
# .roles/vyos_networks/handlers/main.yml
---
- name: Save config
vyos.vyos.vyos_config:
save: true
# ./roles/vyos_networks/tasks/main.yml
- name: "Set up Networks"
vyos.vyos.vyos_config:
src: networks.j2
notify: Save config
Step 2 - Defining Networks
Before we look at the networking template, lets have a look at the networks.yml
file where we define
our networks. We want to put this networks.yml
as a lab
group_vars
because we will be able to
use this for other devices or another vyos firewall with some tweaks later on in a future post.
We also want to separate it from just being a vyos
variable.
./group_vars/lab/networks.yml
networks:
0:
address: 192.168.1.252/24
cidr: 192.168.1.0/24
description: home
gateway: 192.168.1.254/24
firewall:
inside: false
vif: false
interface: eth1
wan: true
1:
address: 10.0.1.254/24
cidr: 10.0.1.0/24
description: devnet
gateway: 10.0.10.254/24
firewall:
inside: true
nat: true
dhcp:
start: 10.0.1.1
stop: 10.0.1.10
vif: false
interface: eth0
10:
address: 10.0.10.254/24
cidr: 10.0.10.0/24
description: vlan10
gateway: 10.0.10.254/24
firewall:
inside: true
nat: true
dhcp:
start: 10.0.10.1
stop: 10.0.10.10
vif: false
interface: eth2
Lets break this down. First we define the dictionary
variable as networks:
then we add our first
network 0:
I chose 0
as it can’t be a vlan
, the idea here is to use these number as vlans
, and
defining the numbers here makes it easier to define a particular vlan and its attributes.
So the first network, network 0
lets have a look at its attributes:
0:
address: 192.168.1.252/24
cidr: 192.168.1.0/24
description: home
gateway: 192.168.1.254/24
firewall:
inside: false
vif: false
interface: eth1
wan: true
First we define the address
we do this with the subnet mask and you will see why when we come to
templates.
Next we define the network cidr
this describes the network as a whole.
After that we give
it a description
which is always handy to have.
gateway
is where we set the nexthop address for this network atleast.
Then we set some firewall
information, we set if this is an inside
network or not
with a truthy
true/false
in this case as this is our WAN
interface network its not.
vif
is where we set if this vlan is going to be a vif
(Virtual Interface). At the moment, all of these
are not vif
but if I can get trunking working in proxmox to be able to use vif
inside Vyos
then
can easily set these and tweak the networks
template.
Next is interface
where we set what interface this network is being connected to.
Lastly wan
where we define if this is a wan
connection or not.
As for the other networks these are set up in a similar way apart from we set the firewall inside to be
true
. And we set some dhcp
options up.
...
dhcp:
start: 10.0.1.1
stop: 10.0.1.10
Step 3 - Templating
Below is the template I used to set up simple networks, where it sets up:
- Interface
- DHCP server for the network
- Enables DNS-Forwarding
- NAT rules for that network
I like to comment my templates as much as possible to help when I come back to look at them to workout what each bit does.
So First thing we do is loop over all networks
I chose interface
as a value.
{% for interface in networks | dict2items -}
This allows me to loop over the networks dictionary as items,
so we can keep adding networks and it will each run will add the new networks.
While in that loop we set up dhcp-server
only if the network has dhcp
as an attribute, this allows
us to create networks that we don’t want dhcp and each device has a static assigned IP. We set the
default-router
by using the gateway
attribute but we split
the /
and just take the first part
of the split which would be the actual IP
we specified.
We then set the name-server
for that network, which we set as the gateway
again, so dhcp tells clients
that its gateway
is also the dns server to use.
Then we set the dhcp
range with start
and stop
values we added, and finally we set the subnet-id to
be the interface.key
this will be the value of the network eg 1
or 10
in our example.
After that we enable dns forwarding
this allows the network to do DNS lookups, we set the allow-from
option to be the whole network so we use the cidr
value.
As we are still in a loop the set service dns forwarding system
does get put in the template each time
a loop over the network is performed, this doesn’t affect the overall configuration but something to
bare in mind, we could fix this by putting it outside of the loop but it makes readability harder.
Last up NAT
I could have done something a bit more clever here but I didn’t so its just using the
description of the network and the cidr
of the network to set the source address
. I then used the
index of the loop to set the rule number, there are other bits we could do like we could have used the
interface.key
value or something.
{# Setup Interfaces #}
{% for interface in networks | dict2items -%}
set interfaces ethernet {{ interface.value.interface }} address {{ interface.value.address }}
set interfaces ethernet {{ interface.value.interface }} description {{ interface.value.description }}
{# Set up DHCP-Server #}
{% if interface.value.dhcp is defined %}
set service dhcp-server shared-network-name {{ interface.value.description }} authoritative
set service dhcp-server shared-network-name {{ interface.value.description }} description '{{ interface.value.description }}'
set service dhcp-server shared-network-name {{ interface.value.description }} subnet {{ interface.value.cidr }} option default-router '{{ interface.value.gateway.split("/")[0] }}'
set service dhcp-server shared-network-name {{ interface.value.description }} subnet {{ interface.value.cidr }} option name-server '{{ interface.value.gateway.split("/")[0] }}'
set service dhcp-server shared-network-name {{ interface.value.description }} subnet {{ interface.value.cidr }} range 0 start '{{ interface.value.dhcp.start }}'
set service dhcp-server shared-network-name {{ interface.value.description }} subnet {{ interface.value.cidr }} range 0 stop '{{ interface.value.dhcp.stop }}'
set service dhcp-server shared-network-name {{ interface.value.description }} subnet {{ interface.value.cidr }} subnet-id '{{ interface.key }}'
{# Enable DNS forwarder #}
set service dns forwarding allow-from '{{ interface.value.cidr }}'
set service dns forwarding listen-address '{{ interface.value.gateway.split("/")[0] }}'
set service dns forwarding system
{# Set up SNAT #}
set nat source rule {{ loop.index }} description '{{ interface.value.description }} via eth1'
set nat source rule {{ loop.index }} outbound-interface name 'eth1'
set nat source rule {{ loop.index }} source address '{{ interface.value.cidr }}'
set nat source rule {{ loop.index }} translation address 'masquerade'
{% endif %}
{% endfor %}
Step 4 - Playbook
Now we just run the playbook ansible-playbook vyos_networks.yml --diff
, for demonstration purposes
I deleted a network and some other config so to show you what the output should look like.
TASK [vyos_networks : Set up Networks] ***************************
[nat source rule]
+ 2 {
+ description "devnet via eth1"
+ outbound-interface {
+ name "eth1"
+ }
+ source {
+ address "10.0.1.0/24"
+ }
+ translation {
+ address "masquerade"
+ }
+ }
[service dhcp-server shared-network-name]
+ devnet {
+ authoritative
+ description "devnet"
+ subnet 10.0.1.0/24 {
+ option {
+ default-router "10.0.10.254"
+ name-server "10.0.10.254"
+ }
+ range 0 {
+ start "10.0.1.1"
+ stop "10.0.1.10"
+ }
+ subnet-id "1"
+ }
+ }
[service dns forwarding]
+ allow-from "10.0.1.0/24"
[edit]
changed: [firewall.lab]
RUNNING HANDLER [vyos_networks : Save config] *******************
changed: [firewall.lab]
PLAY RECAP ******************************************************
firewall.lab ok=3 changed=2 unreachable=0 failed=0 skipped=0
rescued=0 ignored=0
And there we have it, A network defined in yaml
and there is plenty more you can do and bolt on to
this, but I will leave you to have a play.
Next time in Part 5 - Coming Soon We will have a look at templating some Firewall rules.