From ff593670bd4b49c5c939a695b93fb5693d8e4ed3 Mon Sep 17 00:00:00 2001
From: Adar Nimrod <nimrod@shore.co.il>
Date: Thu, 21 Jan 2021 15:06:04 +0200
Subject: [PATCH] Router role.

And playbook. Provision the ns1 host that's also the homelab router.
---
 .pre-commit-config.yaml                     |   1 +
 roles/router/defaults/main.yaml             |   1 +
 roles/router/files/bgpd.conf                |  23 +
 roles/router/files/dhcpd.conf               |  30 ++
 roles/router/files/hosts                    |   6 +
 roles/router/files/mail/spamd.conf          |  45 ++
 roles/router/files/nsd/shore.co.il          |  73 +++
 roles/router/files/nsd/shore_co_il.conf     |   5 +
 roles/router/files/pf.conf                  |  54 +++
 roles/router/files/unbound/shore.co.il.conf |   9 +
 roles/router/handlers/main.yaml             |  77 ++++
 roles/router/tasks/main.yaml                | 479 ++++++++++++++++++++
 roles/router/vars/main.yaml                 |   8 +
 router.yaml                                 |   7 +
 14 files changed, 818 insertions(+)
 create mode 100644 roles/router/defaults/main.yaml
 create mode 100644 roles/router/files/bgpd.conf
 create mode 100644 roles/router/files/dhcpd.conf
 create mode 100644 roles/router/files/hosts
 create mode 100644 roles/router/files/mail/spamd.conf
 create mode 100644 roles/router/files/nsd/shore.co.il
 create mode 100644 roles/router/files/nsd/shore_co_il.conf
 create mode 100644 roles/router/files/pf.conf
 create mode 100644 roles/router/files/unbound/shore.co.il.conf
 create mode 100644 roles/router/handlers/main.yaml
 create mode 100644 roles/router/tasks/main.yaml
 create mode 100644 roles/router/vars/main.yaml
 create mode 100644 router.yaml

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0bd3a64..ab6af0d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,6 +13,7 @@ repos:
     rev: v0.14.3
     hooks:
       - id: detect-secrets
+        exclude: nsd/shore\.co\.il|roles/router/vars/main\.yaml
 
   - repo: https://github.com/adrienverge/yamllint
     rev: v1.25.0
diff --git a/roles/router/defaults/main.yaml b/roles/router/defaults/main.yaml
new file mode 100644
index 0000000..ed97d53
--- /dev/null
+++ b/roles/router/defaults/main.yaml
@@ -0,0 +1 @@
+---
diff --git a/roles/router/files/bgpd.conf b/roles/router/files/bgpd.conf
new file mode 100644
index 0000000..4c447a2
--- /dev/null
+++ b/roles/router/files/bgpd.conf
@@ -0,0 +1,23 @@
+spamdAS="65066"
+
+AS 65001
+fib-update no    # Mandatory, to not update the local routing table
+
+group "spamd-bgp" {
+        remote-as $spamdAS
+        multihop 64
+        announce IPv4 none	# Do not send Route Server any information
+
+	# us.bgp-spamd.net
+        neighbor 64.142.121.62
+
+	# eu.bgp-spamd.net
+	neighbor 217.31.80.170
+
+	# IPv6 eu.bgp-spamd.net
+	neighbor 2a00:15a8:0:100:0:d91f:50aa:1
+}
+
+# 'match' is required, to remove entries when routes are withdrawn
+# This updates the <bgp-spamd-bypass> table in PF
+match from group spamd-bgp community $spamdAS:42  set pftable "bgp-spamd-bypass"
diff --git a/roles/router/files/dhcpd.conf b/roles/router/files/dhcpd.conf
new file mode 100644
index 0000000..9541fb3
--- /dev/null
+++ b/roles/router/files/dhcpd.conf
@@ -0,0 +1,30 @@
+max-lease-time 86400;
+default-lease-time 3600;
+deny unknown-clients;
+authoritative;
+use-host-decl-names on;
+
+subnet 192.168.3.0 netmask 255.255.255.0
+{
+  allow unknown-clients;
+  option domain-name-servers 192.168.3.1;
+  option routers 192.168.3.1;
+  option domain-name "shore.co.il";
+  range 192.168.3.100 192.168.3.199;
+  host kodi
+  {
+    #hardware ethernet ac:f1:df:12:33:24;
+    hardware ethernet 10:c3:7b:9c:b8:fa;
+    fixed-address kodi.shore.co.il;
+  }
+  host ea6350
+  {
+    hardware ethernet 60:38:E0:AE:19:4A;
+    fixed-address ea6350.shore.co.il;
+  }
+  host host01
+  {
+    hardware ethernet C0:7C:D1:C0:02:99;
+    fixed-address host01.shore.co.il;
+  }
+}
diff --git a/roles/router/files/hosts b/roles/router/files/hosts
new file mode 100644
index 0000000..fe35961
--- /dev/null
+++ b/roles/router/files/hosts
@@ -0,0 +1,6 @@
+127.0.0.1	localhost
+::1		localhost
+192.168.3.1	ns1
+192.168.3.11 ea6350.shore.co.il ea6350
+192.168.3.12 xbmc.shore.co.il xbmc kodi.shore.co.il kodi
+192.168.3.17 host01.shore.co.il host01
diff --git a/roles/router/files/mail/spamd.conf b/roles/router/files/mail/spamd.conf
new file mode 100644
index 0000000..9618f26
--- /dev/null
+++ b/roles/router/files/mail/spamd.conf
@@ -0,0 +1,45 @@
+# $OpenBSD: spamd.conf,v 1.4 2012/05/14 16:58:46 beck Exp $
+#
+# spamd(8) configuration file, read by spamd-setup(8).
+# See also spamd.conf(5).
+#
+# Configures lists for spamd(8).
+#
+# Strings follow getcap(3) convention escapes, other than you
+# can have a bare colon (:) inside a quoted string and it
+# will deal with it. See spamd-setup(8) for more details.
+#
+# "all" must be here, and defines the order in which lists are applied.
+# Lists specified with the :white: capability apply to the previous
+# list with a :black: capability.
+#
+# As of November 2004, a place to search for blacklists is
+#     http://spamlinks.net/filter-bl.htm
+
+all:\
+	:uatraps:nixspam:
+
+# University of Alberta greytrap hits.
+# Addresses stay in it for 24 hours from time they misbehave.
+uatraps:\
+	:black:\
+	:msg="Your address %A has sent mail to a ualberta.ca spamtrap\n\
+	within the last 24 hours":\
+	:method=http:\
+	:file=www.openbsd.org/spamd/traplist.gz
+
+# Nixspam recent sources list.
+# Mirrored from http://www.heise.de/ix/nixspam
+nixspam:\
+	:black:\
+	:msg="Your address %A is in the nixspam list\n\
+	See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\
+	:method=http:\
+	:file=www.openbsd.org/spamd/nixspam.gz
+
+# An example of a list containing addresses which should not talk to spamd.
+#
+#override:\
+#	:white:\
+#	:method=file:\
+#	:file=/var/db/override.txt:
diff --git a/roles/router/files/nsd/shore.co.il b/roles/router/files/nsd/shore.co.il
new file mode 100644
index 0000000..033d612
--- /dev/null
+++ b/roles/router/files/nsd/shore.co.il
@@ -0,0 +1,73 @@
+$TTL 1h
+$ORIGIN shore.co.il.
+@               IN      SOA     ns1     hostmaster (
+        2021011602
+        1h
+        5m
+        4w
+        3h )
+
+        IN      NS      ns1
+        IN      NS      ns4
+        IN      A       163.172.74.36
+        IN      TXT     "v=spf1 +mx -all"
+        IN      SPF     "v=spf1 +mx -all"
+        IN      MX      10      smtp
+        IN      CAA     128 issue "letsencrypt.org"
+
+ns1     IN      A       62.219.131.121
+        IN      SPF     "v=spf1 -all"
+        IN      TXT     "v=spf1 -all"
+
+ns4     IN      A       163.172.74.36
+        IN      TXT     "v=spf1 -all"
+        IN      SPF     "v=spf1 -all"
+
+smtp    IN      A       62.219.131.121
+        IN      TXT     "v=spf1 -all"
+        IN      SPF     "v=spf1 -all"
+
+_imaps._tcp IN  SRV 0 1 993 imap
+            IN  TXT "v=spf1 -all"
+            IN  SPF "v=spf1 -all"
+
+_submission._tcp    IN  SRV  0 1 587 smtp
+                    IN  TXT "v=spf1 -all"
+                    IN  SPF "v=spf1 -all"
+
+_smtp._tls  IN  TXT "v=TLSRPTv1;rua=mailto:postmaster@shore.co.il"
+            IN  TXT "v=spf1 -all"
+            IN  SPF "v=spf1 -all"
+
+_mta-sts    IN  TXT "v=STSv1;id=2020072604;"
+            IN  TXT "v=spf1 -all"
+            IN  SPF "v=spf1 -all"
+
+_carddavs._tcp    IN  SRV  0 1 443 nextcloud
+                    IN  TXT "v=spf1 -all"
+                    IN  SPF "v=spf1 -all"
+
+_caldavs._tcp    IN  SRV  0 1 443 nextcloud
+                    IN  TXT "v=spf1 -all"
+                    IN  SPF "v=spf1 -all"
+
+www         IN  CNAME   ns4
+autoconfig  IN  CNAME   ns4
+nextcloud   IN  CNAME   ns1
+git         IN  CNAME   ns1
+lam         IN  CNAME   ns1
+registry    IN  CNAME   ns4
+imap        IN  CNAME   smtp
+mta-sts     IN  CNAME   smtp
+
+host01._domainkey IN    TXT     ("v=DKIM1\; k=rsa\;"
+"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw9EM6TzCofz004vL+aBV"
+"rUcCE2CjIcBw+k50vOir4JkE/+UxAStV/MHT59S0ObjMnkkjR0YCKKJqBPWwaqva"
+"ztZqIj/7g0IsrqoCgVeCcrBEPZ86BN2f4K+r5cWoWwUXtWyVMxJA8J+nnf/7ntLb"
+"e63tzKMZepfDHtbgojG88nyi6rdtdJYOIgVKoNhfLS7K4oxSHGmj0RjCO7CbB/8S"
+"swJhQMwGXCL87iBiQko8e/rqMxbhAuuYRp/ZbM5UXUc+Ds84PRx4TPOxYUC99x2g"
+"TlGIStWa09I0z1JnutqedBrN0uo52DKkA5jLN2xqabZ8RVdVLVmtM50Fbq5EimAK"
+"swIDAQAB\;")
+
+_adsp._domainkey        IN      TXT     "dkim=all;"
+_dmarc  IN      TXT     "v=DMARC1;p=quarantine;pct=100;sp=reject;fo=1;rua=mailto:postmaster@shore.co.il;ruf=mailto:postmaster@shore.co.il;adkim=s;aspf=s"
diff --git a/roles/router/files/nsd/shore_co_il.conf b/roles/router/files/nsd/shore_co_il.conf
new file mode 100644
index 0000000..43a91ca
--- /dev/null
+++ b/roles/router/files/nsd/shore_co_il.conf
@@ -0,0 +1,5 @@
+zone:
+        name: "shore.co.il"
+        zonefile: "shore.co.il"
+        notify: 163.172.74.36 NOKEY #ns4.shore.co.il
+        provide-xfr: 0.0.0.0/0 NOKEY
diff --git a/roles/router/files/pf.conf b/roles/router/files/pf.conf
new file mode 100644
index 0000000..b88d537
--- /dev/null
+++ b/roles/router/files/pf.conf
@@ -0,0 +1,54 @@
+# Policy
+set skip on lo
+set block-policy return
+anchor "ftp-proxy/*"
+block quick inet6 all
+block in quick from <brute>
+block out quick to <brute>
+block drop in quick on egress from <martians>
+block drop out quick on egress to <martians>
+antispoof quick for ingress
+match in all scrub (max-mss 1440)
+
+# Tables
+table <martians> const { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
+10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
+0.0.0.0/8, 240.0.0.0/4 } #non routable address blocks
+table <brute> persist #table for brute force attempts, etc.
+table <bgp-spamd-bypass> persist # table for spamd whitelisted addresses.
+
+# Queues, priorities
+queue egress on pppoe0 bandwidth 50M qlimit 10000
+queue critical parent egress bandwidth 10M max 40M min 1M qlimit 2000
+queue services parent egress bandwidth 10M max 40M qlimit 2000
+queue other parent egress bandwidth 30M max 40M default qlimit 1000
+queue bulk parent egress bandwidth 30M qlimit 200
+match on egress proto { tcp, udp } to port { ssh, isakmp, l2tp, ipsec-nat-t, domain } set queue critical set prio 6
+match on egress proto { ah, esp, gre, icmp } set queue critical set prio 6
+match on egress proto tcp to port { smtp, www, https, submission, imaps } set queue services set prio 4
+match on egress proto { tcp, udp } from kodi.shore.co.il port bittorrent set queue bulk set prio 1
+match on egress proto { tcp, udp } to kodi.shore.co.il port bittorrent set queue bulk set prio 1
+
+# Defaults
+pass in quick proto tcp to (all:0) port ssh keep state (source-track rule, max 100, max-src-nodes 10, max-src-conn-rate 15/60, overload <brute> flush global)
+match out on egress inet from (ingress:network) nat-to (egress)
+block in all
+pass out all
+pass quick inet proto icmp icmp-type { echoreq, unreach }
+
+# Allowed local services
+pass in quick on ingress proto { tcp, udp } to (ingress:0) port { bootps, bootpc } set prio ( 4, 6 )
+pass in quick proto { tcp, udp } to port domain set queue services set prio ( 4, 6 )
+#pass in quick proto tcp to (egress:0) port { www, https } set prio ( 4, 6 )
+
+# Port redirection
+pass in quick proto tcp to (egress:0) port { smtp, submission, imaps, www, https } rdr-to host01.shore.co.il set queue critical set prio ( 4, 6 )
+pass out quick proto tcp to host01.shore.co.il port { submission, smtp, imaps, www, https } received-on ingress nat-to ingress set prio ( 4, 6 )
+#pass in quick proto tcp to (egress:0) port { smtp, submission, imaps } rdr-to host01.shore.co.il set queue critical set prio ( 4, 6 )
+#pass out quick proto tcp to host01.shore.co.il port { submission, smtp, imaps } received-on ingress nat-to ingress set prio ( 4, 6 )
+pass in quick proto { tcp, udp } to (egress:0) port bittorrent rdr-to kodi.shore.co.il set queue bulk set prio 1
+
+# Allowd NAT and proxying
+#pass in quick on ingress inet proto tcp to egress:network port www divert-to localhost port wwwproxy
+pass in quick on ingress inet proto tcp to port ftp divert-to localhost port ftpproxy
+pass in quick on ingress inet to !(ingress:0)
diff --git a/roles/router/files/unbound/shore.co.il.conf b/roles/router/files/unbound/shore.co.il.conf
new file mode 100644
index 0000000..6604d3c
--- /dev/null
+++ b/roles/router/files/unbound/shore.co.il.conf
@@ -0,0 +1,9 @@
+server:
+    interface: 192.168.3.1 #ingress
+    #local-zone: "shore.co.il." static
+    access-control: 192.168.3.0/8 allow
+    access-control: 127.0.0.0/8 allow
+    local-data: "ea6350.shore.co.il.        A   192.168.3.11"
+    local-data: "kodi.shore.co.il.          A   192.168.3.12"
+    local-data: "host01.shore.co.il.        A   192.168.3.17"
+    local-data: "smtp.shore.co.il.          A   192.168.3.17"
diff --git a/roles/router/handlers/main.yaml b/roles/router/handlers/main.yaml
new file mode 100644
index 0000000..7e6d466
--- /dev/null
+++ b/roles/router/handlers/main.yaml
@@ -0,0 +1,77 @@
+---
+- name: Setup network interfaces
+  command:
+    cmd: /bin/sh /etc/netstart
+
+- name: Reload PF
+  command:
+    cmd: pfctl -f /etc/pf.conf
+
+- name: Rebuild mail aliases
+  command:
+    cmd: newaliases
+
+- name: Restart NSD
+  service:
+    name: nsd
+    state: restarted
+
+- name: Restart Unbound
+  service:
+    name: unbound
+    state: restarted
+
+- name: Restart the FTP proxy
+  service:
+    name: ftpproxy
+    state: restarted
+
+- name: Restart the DHCP daemon
+  service:
+    name: dhcpd
+    state: restarted
+
+- name: Restart the SMTP daemon
+  service:
+    name: smtpd
+    state: restarted
+
+- name: Restart the spam deferral daemon
+  service:
+    name: spamd
+    state: restarted
+
+- name: Restart Nginx
+  service:
+    name: nginx
+    state: restarted
+
+- name: Restart the BGP daemon
+  service:
+    name: bgpd
+    state: restarted
+
+- name: Restart the NTP daemon
+  service:
+    name: ntpd
+    state: restarted
+
+- name: Restart the HTTP daemon
+  service:
+    name: httpd
+    state: restarted
+
+- name: Message about restarting the machine
+  debug:
+    msg: The {{ ansible_hostname }} needs to be restarted
+    verbosity: 0
+
+- name: Stop the audio server
+  service:
+    name: sndiod
+    state: stopped
+
+- name: Restart the SSH daemon
+  service:
+    name: sshd
+    state: restarted
diff --git a/roles/router/tasks/main.yaml b/roles/router/tasks/main.yaml
new file mode 100644
index 0000000..a5f38f2
--- /dev/null
+++ b/roles/router/tasks/main.yaml
@@ -0,0 +1,479 @@
+---
+- name: Configure sysctl
+  ignore_errors: true
+  with_dict:
+    net.inet.ip.forwarding: "1"
+  sysctl:
+    name: '{{ item.key }}'
+    value: '{{ item.value }}'
+  tags:
+    - sysctl
+    - network
+    - pf
+
+- name: Set hosts entries
+  copy:
+    dest: /etc/hosts
+    mode: preserve
+    src: hosts
+  diff: true
+  tags:
+    - hosts
+    - dns
+    - network
+    - pf
+
+- name: Set services entries
+  loop:
+    - line: 'wwwproxy		3129/tcp'  # noqa 203
+      regexp: '		3129/tcp'  # noqa 203
+    - line: 'ftpproxy		8021/tcp'  # noqa 203
+      regexp: '		8021/tcp'  # noqa 203
+    - line: 'bittorrent		51413/tcp'  # noqa 203
+      regexp: '		51413/tcp'  # noqa 203
+  lineinfile:
+    backup: true
+    line: '{{ item.line }}'
+    path: /etc/services
+    regexp: '{{ item.regexp }}'
+    state: present
+  tags:
+    - network
+    - pf
+
+- name: Set DNS resolving
+  copy:
+    content: |-
+      search shore.co.il
+      nameserver 127.0.0.1
+      lookup file bind
+    dest: /etc/resolv.conf
+    mode: 0o0644
+  diff: true
+  tags:
+    - resolv
+    - dns
+    - network
+
+- name: Configure the network interfaces
+  with_dict:
+    em1: |
+      inet 192.168.3.1 255.255.255.0
+      description "Connected to internal LAN."
+      group ingress
+      up
+    em5: |
+      description "Connected to DSL modem for PPPoE connection to the ISP."
+      up
+    pppoe0: |
+      inet 62.219.131.121 255.255.255.255 NONE \
+      pppoedev em5 authproto pap \
+      authname 'ns_nimadar@014' authkey '{{ bezeqint_password }}' up
+      dest 0.0.0.1
+      description "The connection to the internet."
+      !/sbin/route add default -ifp pppoe0 62.219.131.121
+  copy:
+    content: '{{ item.value }}'
+    dest: /etc/hostname.{{ item.key }}
+    owner: root
+    group: wheel
+    mode: 0o0600
+  diff: true
+  notify:
+    - Setup network interfaces
+  tags:
+    - interface
+    - network
+
+- name: Configure the Unbound DNS resolver
+  file:
+    path: /var/unbound/etc/unbound.conf.d
+    mode: 0o0755
+    state: directory
+  tags:
+    - unbound
+    - dns
+    - network
+
+- name: Configure Ubnound DNS resolver
+  lineinfile:
+    insertafter: EOF
+    line: >-
+      include: "/var/unbound/etc/unbound.conf.d/*.conf"
+    path: /var/unbound/etc/unbound.conf
+    validate: unbound-checkconf %s
+  notify:
+    - Restart Unbound
+  tags:
+    - unbound
+    - dns
+    - network
+
+- name: Configure the Unbound DNS resolver
+  loop:
+    - shore.co.il.conf
+  copy:
+    dest: '/var/unbound/etc/unbound.conf.d/{{ item }}'
+    mode: preserve
+    src: 'unbound/{{ item }}'
+    validate: unbound-checkconf %s
+  diff: true
+  notify:
+    - Restart Unbound
+  tags:
+    - unbound
+    - dns
+    - network
+
+- name: Enable the Unbound DNS resolver
+  service:
+    enabled: true
+    name: unbound
+  tags:
+    - unbound
+    - dns
+    - network
+
+- name: Configure PF
+  copy:
+    dest: /etc/pf.conf
+    mode: 0o0600
+    src: pf.conf
+    validate: pfctl -nf %s
+  diff: true
+  notify:
+    - Reload PF
+  tags:
+    - pf
+    - network
+
+- name: Enable the FTP proxy
+  service:
+    enabled: true
+    name: ftpproxy
+  notify: Restart the FTP proxy
+  tags:
+    - ftpproxy
+    - network
+
+- name: Apply changes (if needed) to properly setup networking
+  meta: flush_handlers
+  tags:
+    - always
+
+- name: Install packages
+  loop:
+    - bash
+    - curl
+    - git
+    - go
+  openbsd_pkg:
+    name: '{{ item }}'
+    state: present
+  tags:
+    - packages
+
+- name: Allow Bash as a login shell
+  lineinfile:
+    line: /usr/local/bin/bash
+    path: /etc/shells
+  tags:
+    - bash
+
+- name: Set Bash as the login shell
+  user:
+    name: '{{ ansible_env["DOAS_USER"] }}'
+    shell: /usr/local/bin/bash
+  tags:
+    - bash
+
+- name: Set boot configuration
+  copy:
+    content: |
+      stty com1 115200
+      set tty com1
+    mode: 0o0755
+    dest: /etc/boot.conf
+  diff: true
+  notify:
+    - Message about restarting the machine
+  tags:
+    - boot
+
+- name: Configure the NSD DNS server
+  file:
+    path: /var/nsd/etc/nsd.conf.d
+    mode: 0o0755
+    state: directory
+  tags:
+    - nsd
+    - dns
+    - network
+
+- name: Configure the NSD DNS server
+  loop:
+    - line: >-
+        include: "/var/nsd/etc/nsd.conf.d/*.conf"
+      insertafter: EOF
+    - line: >-
+        ip-address: 62.219.131.121
+      insertafter: 'server:'
+  lineinfile:
+    insertafter: '{{ item.insertafter }}'
+    line: '{{ item.line }}'
+    path: /var/nsd/etc/nsd.conf
+    validate: nsd-checkconf %s
+  notify:
+    - Restart NSD
+  tags:
+    - nsd
+    - dns
+    - network
+
+- name: Configure the NSD DNS server
+  loop:
+    - shore_co_il.conf
+  copy:
+    dest: '/var/nsd/etc/nsd.conf.d/{{ item }}'
+    mode: preserve
+    src: 'nsd/{{ item }}'
+    validate: nsd-checkconf %s
+  diff: true
+  notify:
+    - Restart NSD
+  tags:
+    - nsd
+    - dns
+    - network
+
+- name: Configure the NSD DNS server
+  loop:
+    - shore.co.il
+  copy:
+    dest: '/var/nsd/zones/{{ item }}'
+    mode: preserve
+    src: 'nsd/{{ item }}'
+    # validate: nsd-checkzone %s
+  diff: true
+  notify:
+    - Restart NSD
+  tags:
+    - nsd
+    - dns
+    - network
+
+- name: Enable the NSD DNS server
+  service:
+    enabled: true
+    name: nsd
+  tags:
+    - nsd
+    - dns
+    - network
+
+- name: Configure the DHCP daemon
+  copy:
+    dest: /etc/dhcpd.conf
+    mode: preserve
+    src: dhcpd.conf
+    validate: dhcpd -nc %s
+  diff: true
+  notify:
+    - Restart the DHCP daemon
+  tags:
+    - dhcp
+    - network
+
+- name: Enable the DHCP daemon
+  service:
+    enabled: true
+    name: dhcpd
+  notify:
+    - Restart the DHCP daemon
+  tags:
+    - dhcp
+    - network
+
+- name: Configure mail relaying
+  lineinfile:
+    line: action "outbound" relay host host01.shore.co.il
+    path: /etc/mail/smtpd.conf
+    regexp: action "outbound" relay
+    state: present
+    validate: smtpd -nf %s
+  notify:
+    - Restart the SMTP daemon
+  tags:
+    - mail
+
+- name: Configure the spam deferral daemon
+  copy:
+    dest: /etc/mail/spamd.conf
+    mode: preserve
+    src: mail/spamd.conf
+  diff: true
+  notify:
+    - Restart the spam deferral daemon
+  tags:
+    - spamd
+    - mail
+    - network
+
+- name: Enable the spam deferral daemon
+  lineinfile:
+    line: >-
+      spamd_flags="-h smtp.shore.co.il -G25:12:864"
+    path: /etc/rc.conf.local
+  notify:
+    - Restart the spam deferral daemon
+  tags:
+    - spamd
+    - mail
+    - network
+
+- name: Configure mail aliases
+  loop:
+    - root
+    - nimrod
+  lineinfile:
+    line: '{{ item }}: {{ item }}@shore.co.il'
+    path: /etc/mail/aliases
+    state: present
+  notify:
+    - Rebuild mail aliases
+  tags:
+    - aliases
+    - mail
+    - network
+
+- name: Configure the BGP daemon
+  copy:
+    dest: /etc/bgpd.conf
+    mode: 0o0600
+    src: bgpd.conf
+    validate: bgpd -nf %s
+  diff: true
+  notify:
+    - Restart the BGP daemon
+  tags:
+    - bgp
+    - mail
+    - network
+
+- name: Enable the BDP daemon
+  service:
+    enabled: true
+    name: bgpd
+  notify:
+    - Restart the BGP daemon
+  tags:
+    - bgp
+    - mail
+    - network
+
+- name: Configure the NTP daemon
+  copy:
+    content: |
+      server 0.pool.ntp.org
+      server 1.pool.ntp.org
+      server 2.pool.ntp.org
+      server 3.pool.ntp.org
+    dest: /etc/ntpd.conf
+    mode: 0o0644
+    validate: ntpd -nf %s
+  diff: true
+  notify:
+    - Restart the NTP daemon
+  tags:
+    - ntp
+
+- name: Enable the NTP daemon
+  service:
+    enabled: true
+    name: ntpd
+  notify:
+    - Restart the NTP daemon
+  tags:
+    - ntp
+
+- name: Set Cron jobs
+  loop:
+    - job: /sbin/pfctl -t brute -T expire 86400 2>&1 | logger
+      name: PF brute table purge
+      special_time: daily
+    - job: >-
+        {
+        /usr/sbin/unbound-anchor -a /var/unbound/etc/root.key
+        ||
+        /etc/rc.d/unbound restart ;
+        } | logger
+      name: Update DNSSEC root anchor
+      special_time: daily
+    - job: |-
+        { sleep $((RANDOM \% 1800)) && /usr/libexec/spamd-setup; } | logger
+      name: idk
+      special_time: daily
+      state: absent
+  cron:
+    job: '{{ item.job }}'
+    name: '{{ item.name }}'
+    special_time: '{{ item.special_time }}'
+    state: '{{ item.state|default("present") }}'
+    user: root
+  tags:
+    - cron
+    - unbound
+    - pf
+    - network
+    - dns
+
+- name: Disable the audio server
+  service:
+    enabled: false
+    name: sndiod
+  notify:
+    - Stop the audio server
+  tags:
+    - sndiod
+
+- name: Update the host
+  command:
+    cmd: syspatch
+  register: syspatch
+  changed_when: "'Installing' in syspatch.stdout"
+  notify:
+    - Message about restarting the machine
+  tags:
+    - syspatch
+
+- name: Configure the SSH daemon
+  with_dict:
+    PermitRootLogin: 'no'
+    PasswordAuthentication: 'no'
+    KexAlgorithms: '-diffie-hellman-group14-sha1'
+    # yamllint disable-line rule:line-length
+    MACs: '-hmac-sha1,umac-64-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com'
+  lineinfile:
+    line: '{{ item.key }} {{ item.value }}'
+    path: /etc/ssh/sshd_config
+    regexp: '{{ item.key }}'
+    validate: sshd -Tf %s
+  notify:
+    - Restart the SSH daemon
+  tags:
+    - ssh
+
+# yamllint disable-line rule:line-length
+- name: Configure the daily Cron job (skip email if there's nothing to report, report on pending system patches).
+  copy:
+    content: |
+      VERBOSESTATUS=0
+      syspatch -c
+      pkg_add -uInx | grep -v '^quirks'
+    dest: /etc/daily.local
+    group: wheel
+    mode: 0o044
+    owner: root
+  tags:
+    - cron
+    - mail
diff --git a/roles/router/vars/main.yaml b/roles/router/vars/main.yaml
new file mode 100644
index 0000000..5197611
--- /dev/null
+++ b/roles/router/vars/main.yaml
@@ -0,0 +1,8 @@
+---
+bezeqint_password: !vault |
+          $ANSIBLE_VAULT;1.1;AES256
+          31356531363238306161666461643838343036313235306133326134646335386261626438666538
+          6339623132316262363930303631333532653438656134370a656530313161323364326631633635
+          64636433323433646630383638303763636661636535306539663062386437653364386633653065
+          3936646361346465320a323862633262656263366562306332363632643839396233303963343030
+          6633
diff --git a/router.yaml b/router.yaml
new file mode 100644
index 0000000..69b6e43
--- /dev/null
+++ b/router.yaml
@@ -0,0 +1,7 @@
+---
+- hosts:
+    - ns1
+  roles:
+    - router
+  become: true
+  become_user: root
-- 
GitLab