#+BEGIN_SRC conf :tangle private/vars.yml
private_net_cidr: 192.168.56.0/24
+wild_net_cidr: 192.168.57.0/24
public_vpn_net_cidr: 10.177.86.0/24
campus_vpn_net_cidr: 10.84.138.0/24
-gate_wifi_net_cidr: 192.168.57.0/24
#+END_SRC
The network addresses are needed in several additional formats, e.g.
"{{ private_net_cidr | ansible.utils.ipaddr('network') }}"
private_net_mask:
"{{ private_net_cidr | ansible.utils.ipaddr('netmask') }}"
-private_net_and_mask:
- "{{ private_net }} {{ private_net_mask }}"
+private_net_and_mask: "{{ private_net }} {{ private_net_mask }}"
public_vpn_net:
"{{ public_vpn_net_cidr | ansible.utils.ipaddr('network') }}"
public_vpn_net_mask:
"{{ campus_vpn_net_cidr | ansible.utils.ipaddr('netmask') }}"
campus_vpn_net_and_mask:
"{{ campus_vpn_net }} {{ campus_vpn_net_mask }}"
-gate_wifi_net:
- "{{ gate_wifi_net_cidr | ansible.utils.ipaddr('network') }}"
-gate_wifi_net_mask:
- "{{ gate_wifi_net_cidr | ansible.utils.ipaddr('netmask') }}"
-gate_wifi_net_and_mask:
- "{{ gate_wifi_net }} {{ gate_wifi_net_mask }}"
-gate_wifi_broadcast:
- "{{ gate_wifi_net_cidr | ansible.utils.ipaddr('broadcast') }}"
+wild_net: "{{ wild_net_cidr | ansible.utils.ipaddr('network') }}"
+wild_net_mask:
+ "{{ wild_net_cidr | ansible.utils.ipaddr('netmask') }}"
+wild_net_and_mask: "{{ wild_net }} {{ wild_net_mask }}"
+wild_net_broadcast:
+ "{{ wild_net_cidr | ansible.utils.ipaddr('broadcast') }}"
#+END_SRC
The institute prefers to configure its services with IP addresses
Finally, five host addresses are needed frequently in the Ansible
code. The first two are Core's and Gate's addresses on the private
Ethernet. The next two are Gate's and the campus Wi-Fi's addresses on
-the Gate-WiFi subnet, the tiny Ethernet (~gate_wifi_net~) between Gate
-and the (untrusted) campus Wi-Fi access point. The last is Front's
-address on the public VPN, perversely called ~front_private_addr~.
-The following code block picks the obvious IP addresses for Core
-(host 1) and Gate (host 2).
+the "wild" subnet, the untrusted Ethernet (~wild_net~) between Gate
+and the campus Wi-Fi access point(s) and IoT appliances. The last is
+Front's address on the public VPN, perversely called
+~front_private_addr~. The following code block picks the obvious IP
+addresses for Core (host 1) and Gate (host 2).
#+CAPTION: [[file:private/vars.yml][=private/vars.yml=]]
#+BEGIN_SRC conf :tangle private/vars.yml
core_addr_cidr: "{{ private_net_cidr | ansible.utils.ipaddr('1') }}"
gate_addr_cidr: "{{ private_net_cidr | ansible.utils.ipaddr('2') }}"
-gate_wifi_addr_cidr:
- "{{ gate_wifi_net_cidr | ansible.utils.ipaddr('1') }}"
-wifi_wan_addr_cidr:
- "{{ gate_wifi_net_cidr | ansible.utils.ipaddr('2') }}"
+gate_wild_addr_cidr:
+ "{{ wild_net_cidr | ansible.utils.ipaddr('1') }}"
+wifi_wan_addr_cidr: "{{ wild_net_cidr | ansible.utils.ipaddr('2') }}"
front_private_addr_cidr:
"{{ public_vpn_net_cidr | ansible.utils.ipaddr('1') }}"
core_addr: "{{ core_addr_cidr | ansible.utils.ipaddr('address') }}"
gate_addr: "{{ gate_addr_cidr | ansible.utils.ipaddr('address') }}"
-gate_wifi_addr:
- "{{ gate_wifi_addr_cidr | ansible.utils.ipaddr('address') }}"
+gate_wild_addr:
+ "{{ gate_wild_addr_cidr | ansible.utils.ipaddr('address') }}"
wifi_wan_addr:
"{{ wifi_wan_addr_cidr | ansible.utils.ipaddr('address') }}"
front_private_addr:
1. ~lan~ is its main Ethernet interface, connected to the campus's
private Ethernet switch.
- 2. ~wifi~ is its second Ethernet interface, connected to the campus
- Wi-Fi access point's WAN Ethernet interface (with a cross-over
- cable).
+ 2. ~wild~ is its second Ethernet interface, connected to the
+ untrusted network of campus IoT appliances and Wi-Fi access
+ point(s).
3. ~isp~ is its third network interface, connected to the campus
ISP. This could be an Ethernet device connected to a cable
modem. It could be a USB port tethered to a phone, a
#+END_EXAMPLE
#+CAPTION: A small institute using its ISP's Wi-Fi access point.
-In this case Gate has two interfaces and there is no Gate-WiFi subnet.
+In this case Gate has two interfaces and there is no wild subnet
+other than the Internets themselves.
Support for this "alternate" topology is planned but /not/ yet
implemented. Like the original topology, it should require no
Gate was also connected to the USB Ethernet dongles cabled to the
campus Wi-Fi access point and the campus ISP. The three network
adapters are known by their MAC addresses, the values of the variables
-~gate_lan_mac~, ~gate_wifi_mac~, and ~gate_isp_mac~. (For more
+~gate_lan_mac~, ~gate_wild_mac~, and ~gate_isp_mac~. (For more
information, see the Gate role's [[netplan-gate][Configure Netplan]] task.)
At this point Gate was ready for provisioning with Ansible.
RFC3442's extension to encode a second (non-default) static route.
The default route is through the campus ISP at Gate. A second route
directs campus traffic to the Front VPN through Core. This is just an
-example file. The administrator adds and removes actual machines from
-the actual [[file:private/core-dhcpd.conf][=private/core-dhcpd.conf=]] file.
+example file, with MAC addresses chosen to (probably?) match
+VirtualBox test machines. In actual use =private/core-dhcpd.conf=
+refers to a replacement file.
#+CAPTION: [[file:private/core-dhcpd.conf][=private/core-dhcpd.conf=]]
#+BEGIN_SRC conf :tangle private/core-dhcpd.conf :tangle-mode u=rw
hardware ethernet 08:00:27:f3:41:66; fixed-address 192.168.56.3; }
#+END_SRC
-The following tasks install the ISC's DHCP server and configure it
-with the real [[file:private/core-dhcpd.conf][=private/core-dhcpd.conf=]] (/not/ the example above).
+The following tasks install ISC's DHCP server and configure it with
+the real [[file:private/core-dhcpd.conf][=private/core-dhcpd.conf=]] (/not/ the example above).
#+CAPTION: [[file:roles_t/core/tasks/main.yml][=roles_t/core/tasks/main.yml=]]
#+BEGIN_SRC conf :tangle roles_t/core/tasks/main.yml
#+BEGIN_SRC conf
acl "trusted" {
{{ private_net_cidr }};
+ {{ wild_net_cidr }};
{{ public_vpn_net_cidr }};
{{ campus_vpn_net_cidr }};
- {{ gate_wifi_net_cidr }};
localhost;
};
* The Gate Role
-The ~gate~ role configures the services expected at the campus gate: a
-VPN into the campus network via a campus Wi-Fi access point, and
-Internet access via NAT to the Internet. The gate machine uses
-three network interfaces (see [[*The Gate Machine][The Gate Machine]]) configured with
-persistent names used in its firewall rules.
+The ~gate~ role configures the services expected at the campus gate:
+access to the private Ethernet from the untrusted Ethernet (e.g. a
+campus Wi-Fi AP) via VPN, and access to the Internet via NAT. The
+gate machine uses three network interfaces (see [[*The Gate Machine][The Gate Machine]])
+configured with persistent names used in its firewall rules.
- ~lan~ :: The campus Ethernet.
- - ~wifi~ :: The campus Wi-Fi AP.
+ - ~wild~ :: The campus IoT (Wi-Fi APs).
- ~isp~ :: The campus ISP.
-Requiring a VPN to access the campus network from the campus Wi-Fi
-bolsters the native Wi-Fi encryption and frustrates non-RYF ([[https://ryf.fsf.org][Respects
-Your Freedom]]) wireless equipment.
+Requiring a VPN to access the campus network from the untrusted
+Ethernet (a campus Wi-Fi AP) bolsters the native Wi-Fi encryption and
+frustrates non-RYF ([[https://ryf.fsf.org][Respects Your Freedom]]) wireless equipment.
Gate is also a campus machine, so the more generic ~campus~ role is
applied first, by which Gate gets a campus machine's DNS and Postfix
Gate's network interfaces are configured using Netplan and two files.
=/etc/netplan/60-gate.yaml= describes the static interfaces, to the
-campus Ethernet and WiFi. =/etc/netplan/60-isp.yaml= is expected to
+campus Ethernet and Wi-Fi. =/etc/netplan/60-isp.yaml= is expected to
be revised more frequently as the campus ISP changes.
Netplan is configured to identify the interfaces by their MAC
#+CAPTION: [[file:private/vars.yml][=private/vars.yml=]]
#+BEGIN_SRC conf :tangle private/vars.yml
gate_lan_mac: 08:00:27:f3:16:79
+gate_wild_mac: 08:00:27:4a:de:d2
gate_isp_mac: 08:00:27:3d:42:e5
-gate_wifi_mac: 08:00:27:4a:de:d2
#+END_SRC
The following tasks install the two configuration files and apply the
routes:
- to: {{ public_vpn_net_cidr }}
via: {{ core_addr }}
- wifi:
+ wild:
match:
- macaddress: {{ gate_wifi_mac }}
- addresses: [ {{ gate_wifi_addr_cidr }} ]
- set-name: wifi
+ macaddress: {{ gate_wild_mac }}
+ addresses: [ {{ gate_wild_addr_cidr }} ]
+ set-name: wild
dhcp4: false
dest: /etc/netplan/60-gate.yaml
mode: u=rw,g=r,o=
NAT is enabled per the ~ufw-framework(8)~ manual page, by introducing
~nat~ table rules in a block at the end of =/etc/ufw/before.rules=.
They translate packets going to the ISP. These can come from the
-private Ethernet or campus Wi-Fi. Hosts on the other institute
-networks (the two VPNs) should not be routing their Internet traffic
-through their VPN.
+private Ethernet or the untrusted Ethernet (campus IoT, including
+Wi-Fi APs). Hosts on the other institute networks (the two VPNs)
+should not be routing their Internet traffic through their VPN.
#+NAME: ufw-nat
#+CAPTION: ~ufw-nat~
#+BEGIN_SRC conf
--A POSTROUTING -s {{ private_net_cidr }} -o isp -j MASQUERADE
--A POSTROUTING -s {{ gate_wifi_net_cidr }} -o isp -j MASQUERADE
+-A POSTROUTING -s {{ private_net_cidr }} -o isp -j MASQUERADE
+-A POSTROUTING -s {{ wild_net_cidr }} -o isp -j MASQUERADE
#+END_SRC
Forwarding rules are also needed. The ~nat~ table is a /post/ routing
rule set, so the default routing policy (~DENY~) will drop packets
before NAT can translate them. The following rules are added to allow
-packets to be forwarded from the campus Ethernet or Gate-WiFi subnet
+packets to be forwarded from the campus Ethernet or its wild subnet
to an ISP on the ~isp~ interface, and back (if related to an outgoing
packet).
#+CAPTION: ~ufw-forward-nat~
#+BEGIN_SRC conf
-A FORWARD -i lan -o isp -j ACCEPT
--A FORWARD -i wifi -o isp -j ACCEPT
+-A FORWARD -i wild -o isp -j ACCEPT
-A FORWARD -i isp -o lan {{ ACCEPT_RELATED }}
--A FORWARD -i isp -o wifi {{ ACCEPT_RELATED }}
+-A FORWARD -i isp -o wild {{ ACCEPT_RELATED }}
#+END_SRC
To keep the above code lines short, the template references an
#+END_SRC
Note that there are no forwarding rules to allow packets to pass from
-the ~wifi~ device to the ~lan~ device, just the ~ovpn~ device.
+the ~wild~ device to the ~lan~ device, just the ~ovpn~ device.
** Install UFW
future ssh sessions. For this reason, Ansible /does not/ enable the
firewall. The administrator must login and execute the following
command after Gate is configured or new gate is "in position"
-(connected to old Gate's ~wifi~ and ~isp~ networks).
+(connected to old Gate's ~wild~ and ~isp~ networks).
: sudo ufw enable
insertafter: EOF
#+END_SRC
-** Configure DHCP For The Gate-WiFi Ethernet
-
-To accommodate commodity Wi-Fi access points without re-configuring
-them, the institute attempts to look like an up-link, an ISP, e.g. a
-cable modem. Thus it expects the wireless AP to route non-local
-traffic out its WAN Ethernet port, and to get an IP address for the
-WAN port using DHCP. Thus Gate runs ISC's DHCP daemon configured to
-listen on one network interface, recognize exactly one client host,
-and provide that one client with an IP address and customary network
-parameters (default route, time server, etc.).
+** Configure DHCP For The Wild Ethernet
+
+To accommodate commodity Wi-Fi access points, as well as wired IoT
+appliances, without re-configuring them, the institute attempts to
+look like an up-link, an ISP, e.g. a cable modem (aka "router"). It
+expects a wireless AP (or IoT appliance) to route non-local traffic
+out its WAN (or only) Ethernet port, and to get an IP address for that
+port using DHCP. Thus Gate runs ISC's DHCP daemon configured to
+listen on one network interface, recognize a specific list of clients,
+and provide each with an IP address and customary network parameters
+(default route, time server, etc.), much as was done on Core for the
+private Ethernet.
+
+The example configuration file, [[file:private/gate-dhcpd.conf][=private/gate-dhcpd.conf=]], unlike
+[[file:private/core-dhcpd.conf][=private/core-dhcpd.conf=]], does not need RFC3442 (Classless static
+routes). The wild, wired or wireless IoT need know nothing about the
+private network(s). This is just an example file, with a MAC address
+chosen to (probably?) match a VirtualBox test machine. In actual use
+=private/core-dhcpd.conf= refers to a replacement file.
+
+#+CAPTION: [[file:private/gate-dhcpd.conf][=private/gate-dhcpd.conf=]]
+#+BEGIN_SRC conf :tangle private/gate-dhcpd.conf :tangle-mode u=rw
+default-lease-time 3600;
+max-lease-time 7200;
-Two Ansible variables are needed to configure Gate's DHCP service,
-specifically the sole subnet host: ~wifi_wan_name~ is any word
-appropriate for identifying the Wi-Fi AP, and ~wifi_wan_mac~ is the
-AP's MAC address.
+ddns-update-style none;
-#+CAPTION: [[file:private/vars.yml][=private/vars.yml=]]
-#+BEGIN_SRC conf :tangle private/vars.yml
-wifi_wan_mac: 94:83:c4:19:7d:57
-wifi_wan_name: campus-wifi-ap
-#+END_SRC
+authoritative;
-If Gate is configured with ~./abbey config gate~ and then connected to
-actual networks (i.e. /not/ rebooted), the following command is
-executed. If a new gate was configured with ~./abbey config new-gate~
-and not rebooted, the following command would also be executed.
+log-facility daemon;
-: sudo systemctl start isc-dhcp-server
+subnet 192.168.57.0 netmask 255.255.255.0 {
+ option subnet-mask 255.255.255.0;
+ option broadcast-address 192.168.57.255;
+ option routers 192.168.57.1;
+}
-If physically moved or rebooted for some other reason, the above
-command would not be necessary.
+host campus-wifi-ap {
+ hardware ethernet 94:83:c4:19:7d:57;
+ fixed-address 192.168.57.2;
+}
+#+END_SRC
Installation and configuration of the DHCP daemon follows. Note that
-the daemon listens /only/ on the Gate-WiFi network interface. Also
-note the drop-in ~Requires~ dependency, without which the DHCP server
-intermittently fails, finding the ~wifi~ interface has no IPv4
-addresses (or perhaps finding no ~wifi~ interface at all?).
+the daemon listens /only/ on the ~wild~ network interface. Also note
+the drop-in ~Requires~ dependency, without which the DHCP server
+intermittently fails, finding the ~wild~ interface has no IPv4
+addresses (or perhaps finding no ~wild~ interface at all?).
#+CAPTION: [[file:roles_t/gate/tasks/main.yml][=roles_t/gate/tasks/main.yml=]]
#+BEGIN_SRC conf :tangle roles_t/gate/tasks/main.yml
become: yes
lineinfile:
path: /etc/default/isc-dhcp-server
- line: INTERFACESv4="wifi"
+ line: INTERFACESv4="wild"
regexp: ^INTERFACESv4=
notify: Restart DHCP server.
+- name: Configure DHCP subnet.
+ become: yes
+ copy:
+ src: ../private/gate-dhcpd.conf
+ dest: /etc/dhcp/dhcpd.conf
+ notify: Restart DHCP server.
+
- name: Configure DHCP server dependence on interface.
become: yes
copy:
dest: /etc/systemd/system/isc-dhcp-server.service.d/depend.conf
notify: Reload Systemd.
-- name: Configure DHCP for WiFiAP service.
- become: yes
- copy:
- content: |
- default-lease-time 3600;
- max-lease-time 7200;
- ddns-update-style none;
- authoritative;
- log-facility daemon;
-
- subnet {{ gate_wifi_net }} netmask {{ gate_wifi_net_mask }} {
- option subnet-mask {{ gate_wifi_net_mask }};
- option broadcast-address {{ gate_wifi_broadcast }};
- option routers {{ gate_wifi_addr }};
- }
-
- host {{ wifi_wan_name }} {
- hardware ethernet {{ wifi_wan_mac }};
- fixed-address {{ wifi_wan_addr }};
- }
- dest: /etc/dhcp/dhcpd.conf
- notify: Restart DHCP server.
-
-- name: Enable DHCP server.
+- name: Enable/Start DHCP server.
become: yes
systemd:
service: isc-dhcp-server
enabled: yes
+ state: started
#+END_SRC
#+CAPTION: [[file:roles_t/gate/handlers/main.yml][=roles_t/gate/handlers/main.yml=]]
daemon-reload: yes
#+END_SRC
+If Gate is configured with ~./abbey config gate~ and then connected to
+actual networks (i.e. /not/ rebooted), the following command is
+executed. If a new gate was configured with ~./abbey config new-gate~
+and not rebooted, the following command would also be executed.
+
+: sudo systemctl start isc-dhcp-server
+
+If physically moved or rebooted for some other reason, the above
+command would not be necessary.
+
** Install Server Certificate
The (OpenVPN) server on Gate uses an institute certificate (and key)
mysystem "ansible-playbook playbooks/check-inst-vars.yml >/dev/null";
-our ($domain_name, $domain_priv, $front_addr, $gate_wifi_addr);
+our ($domain_name, $domain_priv, $front_addr, $gate_wild_addr);
do "./private/vars.pl";
#+END_SRC
$domain_name = "{{ domain_name }}";
$domain_priv = "{{ domain_priv }}";
$front_addr = "{{ front_addr }}";
- $gate_wifi_addr = "{{ gate_wifi_addr }}";
+ $gate_wild_addr = "{{ gate_wild_addr }}";
dest: ../private/vars.pl
mode: u=rw,g=,o=
#+END_SRC
print "Wrote public VPN configuration to public.ovpn.\n";
}
my $TC = read_file "Secret/gate-shared.key";
- write_template ($DEV,$UP,$CA,$CRT,$KEY,$TC, $gate_wifi_addr,
+ write_template ($DEV,$UP,$CA,$CRT,$KEY,$TC, $gate_wild_addr,
"gate.$domain_priv", "campus.ovpn");
print "Wrote campus VPN configuration to campus.ovpn.\n";
as those in [[file:public/][=public/=]] and [[file:private/][=private/=]], along with the matching EasyRSA
certificate authority and GnuPG key-ring in [[file:Secret/][=Secret/=]] (included in the
distribution), can be used to configure three VirtualBox VMs
-simulating Core, Gate and Front in test networks simulating a campus
-Ethernet, Wi-Fi, ISP, and a commercial cloud. With the test networks
-up and running, a simulated member's notebook can be created and
-alternately attached to the simulated campus Wi-Fi or the Internet (as
-though abroad). The administrator's notebook in this simulation is
-the VirtualBox host.
+simulating Core, Gate and Front in test networks simulating a private
+Ethernet, an untrusted Ethernet, the campus ISP, and a commercial
+cloud. With the test networks up and running, a simulated member's
+notebook can be created and alternately attached to the untrusted
+Ethernet (as though it were on the campus Wi-Fi) or the Internet (as
+though it were abroad). The administrator's notebook in this
+simulation is the VirtualBox host.
The next two sections list the steps taken to create the simulated
Core, Gate and Front machines, and connect them to their networks.
machine at ~192.168.56.10~ pretending to be the administrator's
notebook.
-- ~vboxnet1~ :: Another Host-only network, simulating the tiny
- Ethernet between Gate and the campus Wi-Fi access point. It has no
+- ~vboxnet1~ :: Another Host-only network, simulating the untrusted
+ Ethernet between Gate and the campus IoT (and Wi-Fi APs). It has no
services, no DHCP, just the host at ~192.168.57.2~, simulating the
NATed Wi-Fi network.
~gate~ can then move to the campus. It is shut down before the
following ~VBoxManage~ commands are executed. The commands disconnect
the primary Ethernet interface from ~premises~ and connect it to
-~vboxnet0~. They also create two new interfaces, ~isp~ and ~wifi~,
+~vboxnet0~. They also create two new interfaces, ~isp~ and ~wild~,
connected to the simulated ISP and campus wireless access point.
#+BEGIN_SRC sh
|----------+------------+-----------------+----------------------|
| ~enp0s3~ | ~vboxnet0~ | campus Ethernet | ~gate_lan_mac~ |
| ~enp0s8~ | ~premises~ | campus ISP | ~gate_isp_mac~ |
-| ~enp0s9~ | ~vboxnet1~ | campus wireless | ~gate_wifi_mac~ |
+| ~enp0s9~ | ~vboxnet1~ | campus IoT | ~gate_wild_mac~ |
After ~gate~ boots up with its new network interfaces, the primary
Ethernet interface is temporarily configured with an IP address.