Microsegmentation Linux Server Setup
Microsegmentation is a security technique. You can divide your network into very small, isolated zones and control how they communicate with each other. With Microsegmentation Linux Server Setup, you can create strict rules so that only the right servers can connect on the right ports. In Linux servers, this can be done with host-based firewalls such as nftables, iptables, or higher-level tools like firewalld.
In simple words, Microsegmentation blocks everything and allows only what’s needed. This creates multiple security layers. Even if an attacker breaks into one server, they can’t freely move around the network.
In this guide, we have three groups of servers:
- Web server: This faces the internet and handles HTTP/HTTPS (ports 80 and 443).
- App server: This runs the main application logic and listens on port 8080.
- Database server: This stores your data and listens on port 5432 (Postgres) or 3306 (MySQL).
We will use nftables directly on each server and define simple lists of IPs, so rules are easy to manage.
In short, we are building a strict, least-privilege firewall setup where each server can only talk to the server it needs, and only on the ports it needs.
This works on bare metal, VMs, and cloud instances, with or without Kubernetes. If you are looking for secure and high-performance Bare metal servers, you can explore Perlod Hosting.
Let’s dive into the Microsegmentation Linux Server Setup.
Table of Contents
Prerequisites for Microsegmentation Linux Server Setup
You can use this instruction for Ubuntu 22.04 and 24.04, as well as RHEL 8 and 9. Log in to your server as a root or non-root user with sudo privileges.
Example subnets used in this guide:
- Admin/Mgmt: 10.10.0.0/26
- Web server: 10.10.1.10 – 10.10.1.19
- App server: 10.10.1.20 – 10.10.1.29
- DB server: 10.10.1.30 – 10.10.1.39
Note: When using nftables, remember to disable UFW or firewalld if they are already in use. If you want to use Firewalld, you can proceed to the FirewallD Alternative section.
Step 1. Install and Enable nftables
The first step is to install and enable nftables.
On Ubuntu and Debian-based OS, run the commands below:
apt update
apt install nftables -y
systemctl enable --now nftables
On RHEL, Rocky Linux, or AlmaLinux, run the commands below:
dnf install nftables -y
systemctl enable --now nftables
Step 2. Backup and Validate Current nftables Rules and Config Files
It is recommended that, before you start loading a new ruleset, you back up and validate your current nftables configuration. If you have any rulesets and config files, make a backup of them by using the following commands:
nft list ruleset > /root/nft.rules.backup.$(date +%F-%H%M).nft
[ -f /etc/nftables.conf ] && cp -a /etc/nftables.conf /etc/nftables.conf.bak.$(date +%F-%H%M)
Then, you can validate your config file for errors without loading it by using the following command:
nft -c -f /etc/nftables.conf
You can also immediately load a previous backup ruleset to recover from a bad configuration that locked you out:
nft -f /root/nft.rules.backup.YYYY-MM-DD-HHMM.nft
You must replace the YYYY-MM-DD-HHMM with the timestamp of your backup file.
Step 3. Create a Base nftables Ruleset
At this point, we will use a base ruleset template and only change the role section per server (web/app/db).
First, create the directory with the following command:
mkdir -p /etc/nftables.d
Then, use your desired text editor to create and open the main /etc/nftables.conf file:
nano /etc/nftables.conf
Add the following nftables configuration script to the file:
#!/usr/sbin/nft -f
flush ruleset
# ======== Edit these sets to match your network ========
define ADMIN_NET = { 10.10.0.0/26 }
define WEB_NODES = { 10.10.1.10-10.10.1.19 }
define APP_NODES = { 10.10.1.20-10.10.1.29 }
define DB_NODES = { 10.10.1.30-10.10.1.39 }
table inet filter {
sets {
admin_net { type ipv4_addr; flags interval; elements = $ADMIN_NET; }
web_nodes { type ipv4_addr; flags interval; elements = $WEB_NODES; }
app_nodes { type ipv4_addr; flags interval; elements = $APP_NODES; }
db_nodes { type ipv4_addr; flags interval; elements = $DB_NODES; }
}
chains {
input {
type filter hook input priority 0; policy drop;
# Allow safe basics
ct state { established, related } accept
iif lo accept
# ICMP/ICMPv6 for PMTU and diagnostics
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH from admin network only
ip saddr @admin_net tcp dport 22 accept
# Role-specific inbound rules go here
# (Inserted via /etc/nftables.d/role.nft)
include "/etc/nftables.d/role-input.nft"
# Last resort: log & drop
counter log prefix "NFT-IN-DROP " group 1 level info limit rate 10/second drop
}
output {
type filter hook output priority 0; policy drop;
# Allow replies and loopback
ct state { established, related } accept
oif lo accept
# Minimal OS egress: DNS, NTP, HTTP/S (for updates), CRL/OCSP
udp dport 53 accept
udp dport 123 accept
tcp dport { 80, 443 } accept
# Role-specific egress rules go here
include "/etc/nftables.d/role-output.nft"
# Last resort: log & drop
counter log prefix "NFT-OUT-DROP " group 1 level info limit rate 10/second drop
}
forward {
type filter hook forward priority 0; policy drop;
}
}
}
Once you are done, save and close the file.
This config file:
- Creates a strict, default-deny firewall (all incoming/outgoing traffic is blocked by default).
- Uses defined sets for different groups of servers (web, app, database) and an admin network.
- Allows only minimal, essential traffic (like SSH from admin networks, ICMP, and basic OS egress for updates).
- Includes external files (/etc/nftables.d/role-input.nft) for adding role-specific rules without editing the main file.
- Logs and counts any dropped packets for troubleshooting.
Step 4. Implement A Zero-Trust and Least-Privilege Network Model
At this point, we will define exactly what traffic each type of server (Web, App, DB) is allowed to receive and send.
1. Web Server: It accepts HTTP/HTTPS (ports 80/443) from anyone and can send traffic only to the App server on port 8080.
Create and define the Web input role by using the command below:
cat >/etc/nftables.d/role-input.nft <<'EOF'
tcp dport { 80, 443 } accept
EOF
Create and define the Web output role by using the command below:
cat >/etc/nftables.d/role-output.nft <<'EOF'
ip daddr @app_nodes tcp dport 8080 accept
EOF
2. App Server: It accepts traffic only from the Web server on port 8080 and can send traffic only to the Database server on ports 5432 (PostgreSQL) or 3306 (MySQL).
Create and define the App input role by using the command below:
cat >/etc/nftables.d/role-input.nft <<'EOF'
ip saddr @web_nodes tcp dport 8080 accept
EOF
Create and define the App output role by using the command below:
cat >/etc/nftables.d/role-output.nft <<'EOF'
ip daddr @db_nodes tcp dport { 5432, 3306 } accept
EOF
3. Database Server: It accepts traffic only from the App server on database ports (5432/3306) and can not send anything; it can only send the basic OS traffic from the base rules.
Create and define the Database input role by using the command below:
cat >/etc/nftables.d/role-input.nft <<'EOF'
ip saddr @app_nodes tcp dport { 5432, 3306 } accept
EOF
For Database output role:
cat >/etc/nftables.d/role-output.nft <<'EOF'
# DB nodes typically do not initiate app/data connections.
# Keep only the minimal OS egress allowed by the base rules.
# Add backup/monitoring destinations here if needed.
EOF
Step 5. Activate nftables Ruleset
At this point, you can validate the configuration file for syntax errors with the following command:
nft -c -f /etc/nftables.conf
Then, activate the ruleset immediately with the following command:
nft -f /etc/nftables.conf
Next, enable he nftables service to start automatically at boot :
systemctl enable --now nftables
Finally, you can list the current active ruleset to verify your rules have been loaded correctly:
nft list ruleset
Step 6. Test and Debug nftables Roles
For the functional tests, you can prove the zero-trust model works:
- Web nodes can talk to App nodes.
- App nodes can talk to DB nodes.
- All other direct communication (e.g., Web to DB) is blocked.
- Public internet can only access web services on Web nodes.
From the Web server, you can run:
# Should work: web → app:8080
nc -vz 10.10.1.20 8080
# Should FAIL: web → db:5432 (blocked)
nc -vz 10.10.1.30 5432 || echo "EXPECTED BLOCK"
From the App server, you can run:
# Should work: app → db:5432
nc -vz 10.10.1.30 5432
# Should FAIL: app → internet random ports (blocked by output policy)
nc -vz 1.1.1.1 25 || echo "EXPECTED BLOCK"
From the internet (or another non-web host) to the Web server:
# Should work:
curl -I http://<web-node-ip>
curl -I https://<web-node-ip> # if TLS configured
# Should FAIL to app/db direct ports:
nc -vz <app-node-ip> 8080 || echo "EXPECTED BLOCK"
nc -vz <db-node-ip> 5432 || echo "EXPECTED BLOCK"
For real-time monitoring, you can use the following command, which shows a live trace of how packets are processed by the nftables ruleset, telling you exactly which role accepted or dropped a packet.
nft monitor trace
Also, you can look for the rate-limited drop logs. This shows you what is being blocked.
Check kernel logs with:
journalctl -k -f
Or check /var/log/kern.log (Debian/Ubuntu), depending on your rsyslog/journald setup.
You can also get a detailed view of the active rules with the following command.
The -a (or –handle) flag is essential. It shows a unique number for each rule. You need this handle to delete or update a specific rule later. Also, it displays counters, proving which rules are being used.
nft -a list table inet filter
Step 7. Zero-Downtime Set Updates in nftables Ruleset
At this point, you can dynamically modify the IP addresses in your sets. For example, adding a new server without reloading the entire firewall and disrupting existing connections.
# Add a new app server
nft add element inet filter app_nodes { 10.10.1.25 }
# Remove one
nft delete element inet filter app_nodes { 10.10.1.25 }
Also, you can use the following command to allow for atomic and immediate changes to your defined sets:
nft replace set inet filter app_nodes { type ipv4_addr; elements = { 10.10.1.20-10.10.1.29, 10.10.1.50 } }
Tips for Microsegmentation Setup
At this point, you can consider the following tips for your Microsegmentation Linux Server Setup.
1. Kernel Network Hardening (sysctl): You can configure the Linux kernel itself to be more secure against certain types of network attacks (like IP spoofing and redirects). You can add the following configuration to the /etc/sysctl.d/99-microseg.conf file:
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
- accept_redirects = 0: Ignores malicious ICMP redirect messages.
- rp_filter = 1: Reverse Path Filtering. Blocks packets that arrive on an interface that isn’t the best route back to their source, preventing IP spoofing.
- tcp_syncookies = 1: Protects against SYN flood denial-of-service attacks.
Then, you can apply the changes with:
sysctl --system
2. Allowing Infrastructure Services: You can demonstrate how to punch specific and minimal holes in the strict default-deny policy for essential backend services like backups, monitoring, and internal repositories. You can add acceptance rules to the role-output.nft file of the clients that need to initiate connections to these services. For example, for a backup server like Veeam/proxy, add:
ip daddr { 10.10.2.50 } tcp dport { 2500-3300 } accept
3. Stricter Web Server Roles: To reduce attacks, you can restrict inbound web traffic only to trusted sources like your Load Balancer or Cloudflare’s IP ranges.
In /etc/nftables.d/role-input.nft on the web server, you can replace:
tcp dport { 80, 443 } accept
With:
ip saddr { 203.0.113.0/24, 198.51.100.0/24 } tcp dport { 80, 443 } accept
4. Clean rollback: If you need to revert, you can use your saved backup:
nft -f /root/nft.rules.backup.YYYY-MM-DD-HHMM.nft
Or you can completely disable the firewall (set policy to accept). It should only be used if you are completely locked out and need immediate access before fixing the rules.
nft flush ruleset
FirewallD Alternative for Microsegmentation in RHEL
If you want to use firewalld instead of using nftables in RHEL distributions, you can go forward with these steps.
First, disable nftables and enable firewalld:
systemctl disable --now nftables
systemctl enable --now firewalld
Then, you must create zones for each server and assign server subnets. To create zones, you can run the command below:
firewall-cmd --permanent --new-zone=web
firewall-cmd --permanent --new-zone=app
firewall-cmd --permanent --new-zone=db
Next, assign the sources with the commands below. Adjust the CIDR assignments to cover your exact ranges.
firewall-cmd --permanent --zone=web --add-source=10.10.1.10/31
firewall-cmd --permanent --zone=web --add-source=10.10.1.12/30
firewall-cmd --permanent --zone=web --add-source=10.10.1.16/30
Note: You must continue these commands until all servers are included appropriately.
Now, you must allow per-zone services and ports with the commands below:
# Web: allow HTTP/S from anywhere
firewall-cmd --permanent --zone=web --add-service=http
firewall-cmd --permanent --zone=web --add-service=https
# App: only allow from web → app:8080 (rich rule with source)
firewall-cmd --permanent --zone=app \
--add-rich-rule='rule family="ipv4" source address="10.10.1.10/28" port protocol="tcp" port="8080" accept'
# DB: only allow from app → db ports
firewall-cmd --permanent --zone=db \
--add-rich-rule='rule family="ipv4" source address="10.10.1.20/28" port protocol="tcp" port="5432" accept'
firewall-cmd --permanent --zone=db \
--add-rich-rule='rule family="ipv4" source address="10.10.1.20/28" port protocol="tcp" port="3306" accept'
Also, you must restrict SSH to the admin net only. Apply to all zones or create a dedicated “admin” zone and bind the mgmt NIC to it:
firewall-cmd --permanent \
--add-rich-rule='rule family="ipv4" source address="10.10.0.0/26" service name="ssh" accept'
firewall-cmd --permanent --remove-service=ssh
Finally, make a default drop for everything else:
firewall-cmd --set-default-zone=drop
firewall-cmd --reload
firewall-cmd --list-all-zones | less
With FirewallD, you can add sources and ports easily, but with nftables, you have more control.
FAQs
Which tools can we use for microsegmentation in Linux?
You can use tools like nftables, which is modern and recommended. Also, you can use firewalld, SELinux / AppArmor, and eBPF-based tools like Cilium.
Should we block everything by default in Microsegmentation?
Yes. Best practice is to default deny and allow only what’s required.
Can I combine Microsegmentation with other tools?
Yes, you can combine it with VPNs to secure traffic between zones, use it with IDS/IPS like Suricata for intrusion detection, and use it with monitoring tools like Grafana to check your logs.
Conclusion
Microsegmentation on Linux Server Setup is one of the most effective ways to increase network security. By using host-based firewall rules with tools like nftables, you can be sure each server only communicates with the exact services and ports it truly needs. The setup process may seem difficult, but by following the steps carefully, preparing configs, applying them per server role (Web, App, DB), and testing, you can easily set up your microsegmentation.
If you need reliable VPS hosting services or dedicated servers, you can check out Perlod Hosting.
We hope you enjoy Microsegmentation on Linux Server Setup. Subscribe to our X and Facebook channels to get the latest updates and articles.
For further reading:
Discover VPS Kodee AI Sysadmin
Explore Multi-Cloud Hosting Trends in 2025