Building a network for smaller businesses - Part 2: Running Configurations
In Part 2 of ‘Building a Network for Smaller Businesses” Peter will dive into running configurations on the firewall, with explanations of the design decision made for each service and going through each service one by one.
This series of articles are written by Péter András Rakolcza, a student at Budapest University of Technology and Economics, for his BSc diploma thesis. Peter is a trainee in threat hunting and a full-time BSc Computer Engineer who took interest in CrowdSec’s community-based, open-source approach to cybersecurity.
This is the first thesis paper on CrowdSec published on our website, with many more to come. If you are interested in producing a project around CrowdSec, do not hesitate to contact us at firstname.lastname@example.org.
Before diving into part 2: running configurations, be sure to take a look at the first part of this series, Building a network for small business - Part 1: Hardware.
Configurations running on the firewall
In this article, I will discuss and explain all the configurations running on the firewall in more in-depth. I will go through the services one by one, explaining every design decision I have made. Using this guide, anyone with basic networking knowledge can replicate this setup.
I would like to note that every service should be enabled with the following command to automatically start when the system rebooted:
This yaml file is located under /etc/netplan folder. It is responsible for configuring interfaces. First, using the match keyword, I was able to rename the eno1 to wan0 and enp3s0f0 to lan0 for easier identification. I also set static IP addresses for both interfaces. The other three interfaces are part of the 4-port ethernet adapter which I did not use.
Modifications in the start-up sequence using Systemd derivatives
It was necessary to modify two services’ start-up config file as both NFTables and the CrowdSec Remediation Component rely on the renamed interfaces. Using the following command makes it easy to edit/override service files:
The most important keyword to add or modify is the After derivative. It makes sure that service will not start before the predefined service. This ensures that the interfaces have been properly configured and renamed before NFTables or remediation component. NFTables service configuration file after modification:
NFTables 5.3.1 Definition NFTables is a modern Linux packet classification framework. Iptables is an excellent tool to filter out traffic, perform NAT, log activities and many other things, however, it comes with limitations. These limitations inspired the development of NFTables. It is available with Linux kernel newer than 3.13, it also comes with a new command-line utility called nft. Furthermore, the new structures introduced in NFTables reduces the number of rules that need to be inspected until reaching the final action on a packet.
In the first part, I defined basic variables: VPN interface and the subnet for reserved for the VPN. Also, it resets all nft tables (used to take 10 lines with Iptables).
The first table, filter, is that create IP sets. It is a table that contain IP addresses with expiry dates, I have added two default values in the elements section, the IP of my laptop and desktop PC. This was necessary because I do not want to port knock every single time. Port knocking is integrated in this NFT configuration. The configuration drops every invalid packet right away to optimize processing. We want to accept packets coming from the LAN side, loopback interface or established connections. Furthermore, the config accepts packets coming to port 22 (SSH), if the source IP is in the IP set. I opened UDP port 51820 (for Wireguard), TCP port 80, 443 (for the reverse proxy). Lastly, the service accepts DNS requests coming from the VPN connection, so the user can utilize PiHole when connected via Wireguard.
This is related to prerouting too. It is not enough to accept the packet since it can be passing two interfaces, we also need to forward this in the forward rules. In addition, the service should also forward packets going to the internet. Lastly, as the comment suggests, NFTables forwards WireGuard traffic, allowing it to access the internet via WAN. 38 If you are not counting packets in the post routing, the output chain can be omitted.
In NAT, we are defining what happens to packets that are incoming and destined to another machine behind the firewall. The postrouting chain is about telling what IP should be used for translating IPs coming from various subnets. There are two rules, one for the LAN and one for the VPN. It is faster to set static snat address, however, most people have dynamic addresses, which means masquerading is required.
5.4 arpwatch 5.4.1 Definition
Arpwatch is a simple utility that keeps track for Ethernet / IP address pairings. It logs events into syslog and can report certain changes via email. The utility uses pcap to listen for ARP packets on the preconfigured local ethernet interface.
Arpwatch is a not complex service to configure, but it could make your internal network much more secure. First, you must declare the interface and the subnet where you want arpwatch to listen on.
These are the most important files and its directories:
- /var/arpwatch – default directory
- /var/arpwatch/arp.dat – Main ethernet/ip address records database
- /var/arpwatch/ethercodes.dat – vendor ethernet block list
- /etc/sysconfig/arpwatch – This is the main configuration file
- /usr/sbin/arpwatch – Binary command to start and stop tool using the terminal
- /var/log/messages – It is the system log file where arpwatch writes any changes or unusual
You can further secure this service by notifying someone via email when a new connects to your network. It is done by adding “-m email@example.com” to the arpwatch.conf file.
5.5 Port knocking 5.5.1 Definition
In computer networking, port knocking is a method for opening ports externally by generating connection attempts on a predefined set of closed ports. This makes opening ports more secure and automated scans harder by attackers.
The knockd.conf is the most important file when discussing the service’s configuration. I have setup only one event for SSH, but I could have used this service to further restrict VPN and reverse proxy connections.
- Sequence is the order of ports in the knock. Optionally, you can specify protocol for the given port (TCP is the default).
- Seq_timeout is the timeframe in seconds for the execution of the full sequence to trigger the command. If the time elapses before the knock is complete, it is discarded.
- Tcpflags are the types of packets ports expect to receive. When using TCP flags, knockd will ignore packets that do not match the flags. (TCP SYN is the default flag, as it is the first packet in a TCP connection request)
- Command is the command to be executed when a client makes the correct port-knock. All instances of %IP% will be replaced with the knocker’s IP address. For this example, I have used the nftables to add the IP to the given whitelisted IP set.
The final step is to edit /etc/default/knockd and enable it:
Install the knockd package on the client-side machine, as it includes a tool called knock. To send a knock sequence to the server use:
5.6 Wireguard 5.6.1 Definition
Wireguard in a simple and fast VPN solution with secure cryptography. It aims to replace IPsec, which is a widely used, but rather complicated service. It is designed as a general-purpose solution, it was initially released for Linux, but it is now cross-platform.
VPNs extends a private network across a public network and makes it possible to send data as if their devices were directly connected that specific private network. This has many advantages from security and useability standpoints.
Note: this configuration is IPv4-only but can be extended to support IPv6. This example assumes that clients live within the address space 10.0.0.2 through 10.0.0.254.
It is very important to mention in the lab environment the firewall’s public IP address is a private IP (192.168.1.115), this is because of the double NAT (Figure 16.). Thus, I can only connect to this VPN if I am connected to the home network. This issue is not relevant in a production environment.
16. Double NAT
Wireguard configuration requires modification in the NFTables rules. I have explained these rules more in-depth in the NFTables section 5.3.2.
- Opening the port that WireGuard listens on, 51820 by default
- Allowing Wireguard clients to make DNS requests
- Forwarding client traffic to the internet
- Masquerading traffic so it looks like it comes from the server
5.6.4 Server configuration
Because the setup uses NFTables, I opted to statically configure it rather than supply PreUp/PostUp/PreDown/PostDown hooks in the server configuration .
It is possible to further restrict which client can access other devices connected to the same VPN by adjusting the subnet. For example, I could have used 10.0.0.2/31 for the address to fully isolate this client.
5.6.5 Client(s) configuration
There are two types of configurations: full-tunnel and split-tunnel. For a split- tunnel configuration (only traffic destined for other clients in the VPN network is routed through the VPN). AllowedIPs should be set to 10.0.0.0/24. Using a full-tunnel setup, all traffic is routed through the VPN. I have configured a full-tunnel configuration as I want to use every protective feature of the firewall when I am connected through VPN .
Wireguard is not a particularly “talkative” protocol, so it is considered best practice to use PersisentKeepAlive derivative if you are behind NAT and want WireGuard peer to be able to send you data after a longer pause.
Suricata 5.7.1 Definition
Suricata is a widely used IDS / IPS solution, it is a high-performance, open-source software which is used by many companies to protect their assets. Very large portion of its features are free, but there are many paid extensions for it. This makes the service flexible and affordable.
Suricata is a versatile and complex service to be configured, it can be used in many ways. The service could be very resource-intensive, hence it requires careful decisions. It is important to mention that I am using Suricata as an IDS to reduce complexity. Suricata has the feature set to prevent malicious activity, however, it is working in “safe” mode, so no network packets drop, only warns.
5.7.3 One-time configuration
In the /etc/suricata/suricata.yaml file I have enabled the community-id option and defined which network interface should monitor. In my case, it was the lan0 interface.
Furthermore, I have defined the same interface for packet-captures, but this step is probably not necessary. Live rule reloading is also available, so with this setting in place, when you edit/update your rule sets, changes will take effect without restarting your Suricata service.
By default, the Suricata package has a limited ruleset that only detects the most common Internet Protocols located in the /etc/suricata/rules directory. This can be useful as weaker hardware could be utilized to protect against common threats.
Running the command below updates the Suricata instance.
Next, I have selected the rulesets I want to use in my system. I only chose free rulesets, but there are vendors who offer paid rulesets. Listing all the rulesets:
I installed the two additional rulesets to prevent high CPU usage but detect a big portion of relevant threats: et/open, oisf/trafficid.
It is possible to install open-source rulesets built by the community. There are many free rulesets available on GitHub but exploring these are beyond the scope of this paper. To finalize the installation, I updated the rules once more.
The goal of the installation is to deploy CrowdSec in a multi-security engine setup with one security engine sharing signals with others. This is possible, because the security engine can act as a HTTP REST API server to collect the signals from other security engines. Thus, I could make the firewall as the “main” security engine in the sense that it both collects signals from other security engines, shares information about detected attacks with other local security engines, sends signals to CrowdSec's central API (CAPI) as well as receiving blocklists via CAPI and distributing those to the other security engines.
This ability to function in a distributed setup also means that mitigation does not have to take place on the same security engine as detection. Mitigation is done using remediation components. Remediation components rely on the HTTP REST API served by the “main” CrowdSec Security Engine.
Important files Configuration files:
All data sources and types are defined here
- /etc/crowdsec/bouncers/ Config files for all remediation components
Config file decides what attacks trigger which mitigation and for how long
- /var/log/crowdsec.log CrowdSec Security Engine log file
- /var/log/nameofthebouncer.log The remediation component's log file
Firewall 126.96.36.199 Security Engine
I have installed the following collections from the CrowdSec HUB:
I have installed a single remediation component for the firewall as none of the internal server is hosting a publicly available service. Hence, using crowdsec-firewall-bouncer-nftables was enough to drop any suspicious connection if needed to protect the network.
NextCloud Virtual Machine
Using CrowdSec’s decoupled capability means that I was able to install a security engine to the internal server which is hosting a NextCloud instance. This security engine is configured to report to the firewall (Figure 23.) and use the firewall’s remediation component to do the mitigation. Mitigation could have been done several ways, from simply dropping the connection to introduce captcha to slow down the attack.
5.9.1 DHCP server
A DHCP server is a device on the network configured to provide and assign IP addresses, default gateways and other network parameters to clients. It relies on the standard protocol called Dynamic Host Configuration Protocol to respond broadcast queries.
A DHCP server is essential part of a complete package, running a DHCP server will give addresses to machines in the LAN, which ISP box will not do anymore since it is on the other “side” of the firewall. The most important line in the configuration is the interface which will the service listen on, the IP range and DNS. I have configured the DHCP server to use the local PiHole instance.
I have reserved the 192.168.100.0/24 private network space for the devices. The server will hand out addresses between 192.168.100.5 and 192.168.100.200, closed interval. This leaves space for some connected appliances to have manually configured static IPs.
PiHole 5.9.5 Definition
Pi-Hole – as its name implies – is a network-level Internet ad and tracker blocker which acts as a DNS blackhole. It can be configured as a DHCP server, but this is optional. It was designed for low-powered devices, such as the Rasberry Pi, but compatible with almost any Linux machine. Furthermore, it has the ability to block traditional web advertisements along with ads in not so common places, like smart TVs and mobile operating systems.
This service configures itself during installation. It is very easy to get started and the process is straightforward too. The installation can be started using one command:
After the installation starts, just follow the prompts (Figure 24.) to configure PiHole. One important setting to pay attention to is the Upstream DNS, I chose Cloudflare, it an extremely reliable and fast DNS provider. However, keep in mind all the other providers will work fine here as well.
Finishing the whole process, the web interface (Figure 25.) will be available if visiting the correct static IP address under the /admin page inside the local network.
It is recommended to use PiHole throughout the local network as manually configuring every single device’s DNS is tedious and unnecessary.
Stay tuned for part 3!