AlmaLinux 9.4 multi-NIC routing failures often stem from ambiguous default gateway configurations rather than a non-existent use() function, which is likely a misinterpretation of ip rule or nmcli syntax. Resolving this requires explicitly defining policy-based routing rules via ip route and ip rule to ensure traffic from specific interfaces uses the correct gateway.
Understanding the Routing Ambiguity
When managing multiple network interfaces on AlmaLinux 9.4, the operating system must determine which network interface and corresponding gateway to use for outgoing traffic. By default, Linux uses a single main routing table. If two interfaces are configured with default gateways (routes to0.0.0.0/0), the kernel creates a conflict. The system may randomly select one gateway or prioritize based on metric values, leading to intermittent connectivity loss or asymmetric routing issues.
The term "use()" in the original query appears to be a hallucination or a confusion with command-line flags like --use in older tools, or perhaps a misunderstanding of how NetworkManager handles connections. In modern RHEL-based systems including AlmaLinux and CentOS, routing is managed through the kernel's netlink socket, accessed via commands like ip, route, and sysctl. There is no native function called use() in the networking stack. The issue is almost certainly related to how multiple default routes are prioritized or how policy-based routing is configured to separate traffic flows.
To fix this, you must move beyond simple static configuration and implement source-based routing. This ensures that traffic originating from Interface A always exits via Gateway A, regardless of the destination IP. This approach eliminates ambiguity and provides deterministic behavior for multi-homed servers.
Verifying Current Routing State
Before applying fixes, you must understand the current state of your routing tables. Run the following command to view all active routes:
ip route show
Look for multiple lines starting with default via. If you see more than one, you have identified the root cause of the instability. Additionally, check your network interface names using ip link show to identify which physical or virtual interfaces are involved (e.g., eth0, ens3f0).
You should also inspect the sysctl settings for reverse path filtering. High strictness levels can drop packets if the return path does not match the incoming interface, which is common in multi-NIC setups. Check the current value with:
sysctl net.ipv4.conf.all.rp_filter
If this is set to 1 (strict mode), it may interfere with policy-based routing if not configured correctly. However, changing this is a secondary step; primary focus should be on explicit routing rules.
Implementing Policy-Based Routing
The robust solution involves creating separate routing tables for each network interface and adding rules to direct traffic based on its source IP address. This method replaces the need for any ambiguous "use" logic with explicit kernel directives.
First, create a new routing table file. For example, if your second interface is eth1 with gateway 192.168.2.1 and subnet 192.168.2.0/24, you will define a table ID (e.g., 100) in /etc/iproute2/rt_tables:
echo "100 eth1_table" >> /etc/iproute2/rt_tables
Next, add the route to this new table. This tells the kernel that for table 100, the default gateway is 192.168.2.1:
ip route add default via 192.168.2.1 dev eth1 table 100
Then, add a rule that says: "If the source IP belongs to the 192.168.2.0/24 network, use table 100":
ip rule add from 192.168.2.0/24 table 100
This setup ensures that any traffic originating from the IP range of eth1 will be routed out through eth1's gateway, bypassing the main table's potential conflicts. You must repeat this process for every additional NIC that requires independent routing.
For persistent configuration across reboots, these commands should be added to your network script files or managed via NetworkManager dispatcher scripts, depending on your distribution's preferred method. On AlmaLinux 9, NetworkManager is the standard, so you may prefer configuring these as part of the connection profile using nmcli properties like ipv4.route-table-id.
Configuring via NetworkManager
Using NetworkManager simplifies persistence. You can assign a specific route table to a connection profile. For a connection named eth1, you can set the route table ID:
nmcli connection modify eth1 ipv4.route-table-id 100
Then, ensure the connection has the correct gateway and DNS settings. When the connection comes up, NetworkManager will automatically apply the necessary ip rule and ip route commands to enforce the separation. This is generally safer than manual scripting because it integrates with the system's lifecycle management. Verify the changes by bringing the connection down and up again:
nmcli connection down eth1 && nmcli connection up eth1
Check the routing table again to confirm that the rule and route are present.
Troubleshooting Connectivity
After implementing policy-based routing, test connectivity from both interfaces. Use curl ifconfig.me or wget -qO- ipinfo.io from hosts behind each interface to verify the exit IP matches the expected interface. If connectivity fails, check the ARP cache with ip neigh show to ensure the gateway MAC addresses are resolved.
If you encounter issues where traffic still leaks to the wrong interface, verify that your firewall rules (firewalld or nftables) are not blocking the source IPs associated with the new routing rules. Asymmetric routing can sometimes trigger security modules to drop packets even if the routing table is correct.
For complex scenarios involving virtual machines or containers, refer to guides on configuring traffic routes between VMs to ensure your host-level routing does not conflict with guest-level networking. Similarly, if you are using VPNs alongside multi-NIC setups, consult troubleshooting resources for client-to-client communication to ensure tunnel interfaces do not override your base routing rules.
Frequently Asked Questions
Why did I get an error about 'use' being undefined?
The use() function does not exist in AlmaLinux or CentOS networking utilities. This error likely stems from a typo in a script or a confusion with Python libraries or other programming contexts. Stick to standard CLI tools like ip, route, and nmcli for network configuration.
Can I have two default gateways without policy-based routing?
Technically yes, but it is highly discouraged. The kernel will use the route with the lowest metric, and failover behavior is unpredictable. Without policy-based routing, you cannot guarantee which interface handles specific traffic, leading to connection drops for services bound to specific subnets.
How do I make ip route changes permanent?
On AlmaLinux 9, the best practice is to configure these settings within NetworkManager connection profiles using nmcli. Alternatively, you can place commands in /etc/sysconfig/network-scripts/ifup-local or use systemd-networkd if you have migrated away from NetworkManager, though NM is the default.
What is the difference between ip rule and ip route?
ip route defines the actual paths to destinations (the map). ip rule defines the conditions under which specific routing tables are used (the decision logic). You need both to implement source-based routing: rules select the table, and routes define the path within that table.
Will this affect my existing SSH connections?
If you change routing while connected, existing TCP connections remain bound to their initial interface. New connections will follow the new rules. To avoid disruption, apply changes during a maintenance window or ensure your management IP is included in the correct routing rule so you don't lock yourself out.