Startseite Automatisierung - Ansible - pfSense
Eintrag
Abbrechen

Automatisierung - Ansible - pfSense

Ansbile ist aktuell das Tool um Netzwerkequipment automatisch konfigurieren zu lassen. Im aktuellen Beispiel wird eine pfSense mittels Playbooks konfiguriert.

Derzeit ist es nicht möglich, virtuelle IPs über Ansible einrichten zu lassen. Clusterkonfigurationen müssen derzeit weiter per Hand eingerichtet werden.

Vorbereitung

Es muss das Modul “pfsensible.core” installiert werden. Ansible muss ebenfalls installiert sein, siehe hier.

Auf der pfSense muss sudo installiert sein.

1
ansible-galaxy collection install pfsensible.core

Es wird folgende Ordnerstruktur angelegt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pfsense/
├── ansible.cfg
├── group_vars
│   └── all.yml
├── hosts
├── pb_pfsense_add_aliases.yml
├── pb_pfsense_add_if_pwf01.yml
├── pb_pfsense_add_if_pwf02.yml
├── pb_pfsense_add_if.yml
├── pb_pfsense_add_lab_net.yml
├── pb_pfsense_add_nat.yml
├── pb_pfsense_add_rules.yml
├── pb_pfsense_add_vlans.yml
├── pb_pfsense_del_aliases.yml
├── pb_pfsense_del_if_pwf01.yml
├── pb_pfsense_del_if_pwf02.yml
├── pb_pfsense_del_if.yml
├── pb_pfsense_del_lab_net.yml
├── pb_pfsense_del_nat.yml
├── pb_pfsense_del_rules.yml
└── pb_pfsense_del_vlans.yml

Ziel

Das Ziel ist es, zwei Netze einzurichten, die per VLAN-Tagging an das interne “LAN-Interface” der Firewall angebunden ist. Diese sollen per NAT auf die WAN-IP übersetzt werden, es soll als Start nur Surfen erlaubt sein.

Konfiguration und Inventory

Die Konfiguration von Ansbile sieht wie folgt aus:

1
2
3
4
5
6
7
8
9
10
[defaults]
inventory=hosts
retry_files_enabled=False
gathering=explicit
host_key_checking=False
action_warnings=False
deprecation_warnings=False
ansible_command_timeout=600
command_timeout=600
ask_pass=True

Das Inventory sieht folgendermaßen aus:

1
2
3
4
5
[dmzfirewall]
pf01    ansible_host=10.10.10.50

[dmzfirewall:vars]
ansible_python_interpreter=auto

Der Interpreter muss auf “auto” gesetzt werden, andernfalls bricht Ansible mit Fehlern ab, sobald mehr als ein Objekt eingerichtet wird.

Playbooks

Folgende Playbooks werden erstellt, um Netze anzulegen.

pb_pfsense_add_vlans.yml

Im ersten Schritt werden VLANs angelegt.

Wichtig: die Items müssen im Modul mit doppelten, geschweiften Klammern ({}) geschrieben werden. Dies gilt für alle Playbooks dieses Artikels.

Leider zeigt Jekyll die Notation nicht richtig an.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
- name: create vlans
  hosts: dmzfirewall
  remote_user: admin
  become: yes
  become_method: sudo
  become_user: root

  tasks:

  - name: create vlans
    pfsensible.core.pfsense_vlan:
      interface: "{ item.if }"
      vlan_id: "{ item.vid }"
      descr: "{ item.descr }"
      state: present

    loop:
      - { if: 'em2', vid: '555', descr: 'LAB_Test55' }
      - { if: 'em2', vid: '556', descr: 'LAB_Test56' }

pb_pfsense_add_if.yml

Jetzt werden Interfaces konfiguriert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
---
- name: create interface pwf01
  hosts: pf01
  remote_user: admin
  become: yes
  become_method: sudo
  become_user: root

  tasks:

  - name: create interface on pwf01
    pfsensible.core.pfsense_interface:
      interface: "{ item.if }"
      ipv4_address: "{ item.ipv4 }"
      ipv4_prefixlen: "{ item.prefixv4 }"
      ipv4_type: static
      descr: "{ item.descr }"
      state: present
      enable: true

    loop:
      - { if: 'em2.555', ipv4: '172.17.55.1', prefixv4: '24', descr: '17_LAB_Test55' }
      - { if: 'em2.556', ipv4: '172.17.56.1', prefixv4: '24', descr: '17_LAB_Test56' }

pb_pfsense_add_aliases.yml

Es werden Aliases angelegt, was das Regelwerk leichter lesbar macht.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---
- name: create aliases
  hosts: dmzfirewall
  remote_user: admin
  become: yes
  become_method: sudo
  become_user: root


  tasks:

  - name: create host alias(es)
    pfsensible.core.pfsense_alias:
      name: "{ item.name }"
      address: "{ item.address }"
      descr: "{ item.descr }"
      type: "{ item.type }"
      state: present

    loop:
      - { name: 'VIP_lab_Test55', address: '172.17.55.1', descr: 'GW IP LAB Test55', type: 'host' }
      - { name: 'VIP_lab_Test56', address: '172.17.56.1', descr: 'GW IP LAB Test56', type: 'host' }
      - { name: 'NET_lab_test55', address: '172.17.55.0/24', descr: 'Netz LAB Test55', type: 'network' }
      - { name: 'NET_lab_test56', address: '172.17.56.0/24', descr: 'Netz LAB Test56', type: 'network' }

pb_pfsense_add_nat.yml

Die Netze werden auf die WAN IP genat’ed. Wichtig: die Outbound NAT muss auf manuell gesetzt sein.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---
- name: create nat
  hosts: dmzfirewall
  remote_user: admin
  become: yes
  become_method: sudo
  become_user: root

  tasks:

  - name: create outbound nat
    pfsensible.core.pfsense_nat_outbound:
      descr: "{ item.descr }"
      interface: "{ item.if }"
      address: "{ item.addr }"
      source: "{ item.source }"
      destination: any
      protocol: any
      before: bottom
      state: present

    loop:
      - { descr: 'NAT_LAB_Test55', if: 'wan', addr: '10.10.10.10', source: '172.17.55.0/24' }
      - { descr: 'NAT_LAB_Test56', if: 'wan', addr: '10.10.10.10', source: '172.17.56.0/24' }

pb_pfsense_add_rules.yml

Jetzt wird das Regelwerk erstellt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
---
- name: create std rule and separators
  hosts: dmzfirewall
  remote_user: admin
  become: yes
  become_method: sudo
  become_user: root

  tasks:

  - name: create icmp rule
    pfsensible.core.pfsense_rule:
      action: pass
      interface: "{ item.if }"
      ipprotocol: inet
      protocol: icmp
      icmptype: echorep, echoreq
      source: "{ item.source }"
      destination: any
      name: permit_ping
      state: present

    with_items:
      - { if: '17_LAB_TEST55', source: 'NET_lab_test55' }
      - { if: '17_LAB_TEST56', source: 'NET_lab_test56' }

  - name: create standard rules
    pfsensible.core.pfsense_rule:
      action: "{ item.action }"
      interface: "{ item.if }"
      ipprotocol: "{ item.ipproto }"
      protocol: "{ item.protocol }"
      source: "{ item.source }"
      destination: "{ item.destination }"
      destination_port: "{ item.dport }"
      name: "{ item.name }"
      state: present

    loop:
      - { action: 'pass', if: '17_LAB_TEST55', ipproto: 'inet', protocol: 'tcp/udp', source: 'NET_lab_test55', destination: 'VIP_lab_Test55', dport: '53', name: 'permit_dns' }
      - { action: 'pass', if: '17_LAB_TEST55', ipproto: 'inet', protocol: 'tcp/udp', source: 'NET_lab_test55', destination: 'grp_DNS_Server', dport: '53', name: 'permit_dns_grp' }
      - { action: 'pass', if: '17_LAB_TEST55', ipproto: 'inet', protocol: 'udp', source: 'NET_lab_test55', destination: 'VIP_lab_Test55', dport: '123', name: 'permit_ntp' }
      - { action: 'pass', if: '17_LAB_TEST55', ipproto: 'inet', protocol: 'udp', source: 'NET_lab_test55', destination: 'grp_NTP_Server', dport: '123', name: 'permit_ntp_grp' }
      - { action: 'pass', if: '17_LAB_TEST55', ipproto: 'inet', protocol: 'tcp', source: 'NET_lab_test55', destination: 'any', dport: 'srv_web_tcp', name: 'permit_http_s' }
      - { action: 'pass', if: '17_LAB_TEST56', ipproto: 'inet', protocol: 'tcp/udp', source: 'NET_lab_test56', destination: 'VIP_lab_Test56', dport: '53', name: 'permit_dns' }
      - { action: 'pass', if: '17_LAB_TEST56', ipproto: 'inet', protocol: 'tcp/udp', source: 'NET_lab_test56', destination: 'grp_DNS_Server', dport: '53', name: 'permit_dns_grp' }
      - { action: 'pass', if: '17_LAB_TEST56', ipproto: 'inet', protocol: 'udp', source: 'NET_lab_test56', destination: 'VIP_lab_Test56', dport: '123', name: 'permit_ntp' }
      - { action: 'pass', if: '17_LAB_TEST56', ipproto: 'inet', protocol: 'udp', source: 'NET_lab_test56', destination: 'grp_NTP_Server', dport: '123', name: 'permit_ntp_grp' }
      - { action: 'pass', if: '17_LAB_TEST56', ipproto: 'inet', protocol: 'tcp', source: 'NET_lab_test56', destination: 'any', dport: 'srv_web_tcp', name: 'permit_http_s' }


  - name: create separator general
    pfsensible.core.pfsense_rule_separator:
      name: General Rules
      color: warning
      interface: "{ item.if }"
      after: top
      state: present

    with_items:
      - { if: '17_LAB_TEST55' }
      - { if: '17_LAB_TEST56' }

  - name: create separator network
    pfsensible.core.pfsense_rule_separator:
      name: Network Rules
      color: info
      interface: "{ item.if }"
      after: permit_ping
      state: present

    with_items:
      - { if: '17_LAB_TEST55' }
      - { if: '17_LAB_TEST56' }

pb_pfsense_add_lab_net.yml

Alle Playbooks werden zusammengefasst.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
- name: setting vlans
  import_playbook: pb_pfsense_add_vlans.yml

- name: setting ips
  import_playbook: pb_pfsense_add_if.yml

- name: setting alias
  import_playbook: pb_pfsense_add_aliases.yml

- name: setting nat
  import_playbook: pb_pfsense_add_nat.yml

- name: setting rules
  import_playbook: pb_pfsense_add_rules.yml

Damit wurde pfSense mittels Ansible konfiguriert.

Leider gibt es derzeit kein Modul um den DHCP-Server zu aktivieren.

Lediglich statische DHCP-Mappings können per Ansbile eingerichtet werden.