How to use domain routing in Access Server to manage dynamic IP addresses and enforce group-based access in split tunnel VPN deployments.
This tutorial explains how to configure and validate domain routing in Access Server. Domain routing allows you to route traffic based on domain names instead of IP addresses, which is especially useful when application IPs change frequently or when access must be restricted by user or group.
This tutorial uses two practical scenarios in a split tunnel deployment:
Brandon manages IT and networking for a company that uses Access Server in split tunnel mode to provide employees with remote access to a private application.
The private application is accessed via an internal domain name (app1.example.com). Previously, Brandon had to configure access control rules using the application's IP address. Because the IP changes over time, this required frequent manual updates.
Using domain routing, Brandon can configure rules based on the application's domain name instead of its IP address, eliminating the need for ongoing rule changes.
The same company has two departments: Sales and Support.
-
The Sales team needs access to
app2.example.com. -
The Support team needs access to
app3.example.com.
Brandon must ensure that users can access only the applications assigned to their department. Domain routing, combined with group-based access rules, allows him to enforce this separation.
-
Access Server 3.1.0 or newer.
-
Admin Web UI access.
-
DNS server proxy enabled globally.
-
One or more users or groups configured in Access Server.
Note
In our documentation, we use example IPv4 addresses and subnets reserved for documentation, such as 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24.
Ensure you replace them with valid IPv4 addresses and subnets for your network(s).
In this step, you create a global domain routing rule for app1.example.com. Global rules apply to all users.
-
Sign in to the Admin Web UI.
-
Click Access Controls.
-
The Group and User Access Rules tab displays.
-
-
Click the Global Access Rules tab.
-
Under Domains, select the global routing mode:
-
NAT — The source IP appears as the Access Server private IP address when traffic reaches internal resources.
-
-
Specify a domain or wildcard domain in the Domains text field:
app1.example.com
-
Click Save and Restart.
-
Connect to your console and get root privileges.
-
List the global ruleset:
sacli AccessControlRulesetsList
-
Example output:
[ { "comment": "Default ruleset for global domain rules", "id": 1, "name": "__DEFAULT___default_ruleset", "owner": "__DEFAULT__", "owner_type": "user_default", "position": 0 } ]
-
-
Note the
idvalue (in this example,1). -
List the rules in the ruleset:
sacli --ruleset_id '1'1 AccessControlRulesList
Replace the
ruleset_idvalue with the value from the previous example output.-
Example output:
[ { "action": "nat", "comment": "", "id": 1, "match_data": "app1.example.com", "match_type": "domain", "position": 0, "ruleset_id": 1, "type": "domain_routing" } ]
-
This confirms that the domain routing rule is configured correctly.
In this step, users connect to the VPN and generate traffic to app1.example.com, which we can verify.
-
Connect a VPN client to the server.
-
On the Access Server, start a packet capture:
tcpdump -eni any icmp
-
From the VPN client, run:
ping app1.example.com
-
Example output from the VPN client:
root@brandon:~# ping app1.example.com -c 1 PING app1.example.com (100.64.0.1) 56(84) bytes of data. 64 bytes from 100.64.0.1: icmp_seq=1 ttl=53 time=3.46 ms --- app1.example.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 3.456/3.456/3.456/0.000 ms
-
Example tcpdump output from the Access Server:
01:27:02.133777 as0t2 In ifindex 340 ethertype IPv4 (0x0800), length 104: 172.27.232.2 > 100.64.0.1: ICMP echo request, id 36543, seq 1, length 64 01:27:02.133798 eth0 Out ifindex 2 2a:db:03:a7:44:c9 ethertype IPv4 (0x0800), length 104: 64.227.6.171 > 192.0.2.1: ICMP echo request, id 36543, seq 1, length 64 01:27:02.136814 eth0 In ifindex 2 fe:00:00:00:01:01 ethertype IPv4 (0x0800), length 104: 192.0.2.1 > 64.227.6.171: ICMP echo reply, id 36543, seq 1, length 64 01:27:02.136874 as0t2 Out ifindex 340 ethertype IPv4 (0x0800), length 104: 100.64.0.1 > 172.27.232.2: ICMP echo reply, id 36543, seq 1, length 64
-
The VPN client results show:
-
The real IP of
app1.example.comis192.0.2.1. -
Access Server maps this to an internal IP (
100.64.0.1) from the DNS internal IP range (100.64.0.0/10by default). -
This mapping ensures traffic is routed through the VPN tunnel.
Note
You can view or change this internal IP range in the Admin Web UI at: VPN Server > Subnets > DNS internal IP range.
The tcpdump output confirms NAT translation between the mapped and real IPs.
-
Run the following to verify that your VPN IP is associated with the real IP of
app1.example.com(192.0.2.1) and the mapped IP (100.64.0.1):nft list chain ip as_nat AS_DOMAIN_RT
-
Example output:
table ip as_nat { chain AS_DOMAIN_RT { ip saddr 172.27.232.2 ip daddr 100.64.0.1 meta mark set meta mark | 0x08000000 ip saddr 172.27.232.2 ip daddr 100.64.0.1 dnat to 192.0.2.1 } } -
This confirms that the domain routing rules have been correctly applied at the firewall level.
-
We'll create separate rules for the Sales and Support groups.
Sales group
-
Sign in to the Admin Web UI.
-
Click Groups and select Sales.
-
Click the Access Rules tab.
-
Click New Access Rule.
-
In the Address field, enter a domain:
app2.example.com
Note
Ensure you use an exact domain.
-
Select NAT as the destination type.
-
Observe that the Protocol and Port fields are disabled when a domain is entered.
-
Click Save rule and Restart.
Support group
Repeat the same steps for the Support group, using:
app3.example.com
From the Admin Web UI
-
Click Access Controls.
-
The Group and User Access Rules tab is displayed.
-
-
Confirm that each domain appears correctly in the Destination column for the corresponding group.
From the CLI
-
Connect to the console and get root privileges.
-
List group rulesets:
sacli AccessControlRulesetsList
-
Example output:
[ { "comment": "Auto-created ruleset for group Sales", "id": 2, "name": "Ruleset for Sales", "owner": "Sales", "owner_type": "group", "position": 1 }, { "comment": "Auto-created ruleset for group Support", "id": 3, "name": "Ruleset for Support", "owner": "Support", "owner_type": "group", "position": 1 } ]
-
-
Identify the ruleset IDs for the Sales and Support groups.
-
Using the ID values, list the rules for each ruleset:
sacli --ruleset_id '2' AccessControlRulesList sacli --ruleset_id '3' AccessControlRulesList
-
Example outputs:
[ { "action": "nat", "comment": "", "id": 1, "match_data": "app2.example.com", "match_type": "domain", "position": 1, "ruleset_id": 2, "type": "domain_routing" } ][ { "action": "nat", "comment": "", "id": 2, "match_data": "app3.example.com", "match_type": "domain", "position": 1, "ruleset_id": 3, "type": "domain_routing" } ]
-
-
Verify that:
-
Sales has a rule for
app2.example.com. -
Support has a rule for
app3.example.com.
-
-
Start
tcpdumpon Access Server:tcpdump -eni any icmp
-
From a Sales user VPN client:
ping app2.example.com
-
Example output:
root@sales:~# ping app2.example.com -c 1 PING app2.example.com (100.64.0.2) 56(84) bytes of data. 64 bytes from 100.64.0.2: icmp_seq=1 ttl=53 time=3.64 ms --- app2.example.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 3.635/3.635/3.635/0.000 ms
-
The real IP of
app2.example.comis192.0.2.2. -
Access Server maps this to an internal IP (
100.64.0.2) from the DNS internal IP range (100.64.0.0/10by default). -
This mapping ensures traffic is routed through the VPN tunnel.
-
-
From a Support user VPN client:
ping app3.example.com
-
Example output:
root@support:~# ping app3.example.com -c 1 PING app3.example.com (100.64.0.3) 56(84) bytes of data. 64 bytes from 100.64.0.3: icmp_seq=1 ttl=53 time=3.64 ms --- app3.example.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 3.635/3.635/3.635/0.000 ms
-
The real IP of
app3.example.comis192.0.2.3. -
Access Server maps this to an internal IP (
100.64.0.3) from the DNS internal IP range (100.64.0.0/10by default). -
This mapping ensures traffic is routed through the VPN tunnel.
-
-
The Access Server
tcpdumpoutputs confirm NAT translation between the real IP address and the mapped IP address.02:41:45.884195 as0t3 In ifindex 341 ethertype IPv4 (0x0800), length 104: 172.27.248.2 > 100.64.0.3: ICMP echo request, id 36990, seq 1, length 64 02:41:45.884219 eth0 Out ifindex 2 2a:db:03:a7:44:c9 ethertype IPv4 (0x0800), length 104: 64.227.6.171 > 192.0.2.3: ICMP echo request, id 36990, seq 1, length 64 02:41:45.946690 eth0 In ifindex 2 fe:00:00:00:01:01 ethertype IPv4 (0x0800), length 104: 192.0.2.3 > 64.227.6.171: ICMP echo reply, id 36990, seq 1, length 64 02:41:45.946727 as0t3 Out ifindex 341 ethertype IPv4 (0x0800), length 104: 100.64.0.3 > 172.27.248.2: ICMP echo reply, id 36990, seq 1, length 64
Each domain resolves to a mapped IP in the internal pool and is routed correctly through the VPN tunnel.
-
Run the following to verify that your VPN IP is associated with the real IP of
app2.example.com(192.0.2.2) andapp3.example.com(192.0.2.3), and the mapped IPs (100.64.0.2and100.64.0.3).nft list chain ip as_nat AS_DOMAIN_RT
-
Example output:
table ip as_nat { chain AS_DOMAIN_RT { ip saddr 172.27.240.2 ip daddr 100.64.0.2 meta mark set meta mark | 0x08000000 ip saddr 172.27.240.2 ip daddr 100.64.0.2 dnat to 192.0.2.2 ip saddr 172.27.248.3 ip daddr 100.64.0.3 meta mark set meta mark | 0x08000000 ip saddr 172.27.248.3 ip daddr 100.64.0.3 dnat to 192.0.2.3 } } -
This confirms that domain routing and group-based access are functioning as expected.
-
Comments
0 comments
Article is closed for comments.