Skip to main content

Tutorial: Step-by-Step Examples for Split Tunnel and Role-Based Access Using Domain Routing

Abstract

How to use domain routing in Access Server to manage dynamic IP addresses and enforce group-based access in split tunnel VPN deployments.

Overview

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:

Scenario 1: Domain routing for applications with dynamic IPs

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.

Scenario 2: Domain routing with department-based access

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.

Prerequisites

  • 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).

Step-by-Step: Scenario 1 — Domain routing for an application with a dynamic IP

In this step, you create a global domain routing rule for app1.example.com. Global rules apply to all users.

  1. Sign in to the Admin Web UI.

  2. Click Access Controls.

    • The Group and User Access Rules tab displays.

  3. Click the Global Access Rules tab.

  4. Under Domains, select the global routing mode:

    • NAT — The source IP appears as the Access Server private IP address when traffic reaches internal resources.

  5. Specify a domain or wildcard domain in the Domains text field:

    app1.example.com
  6. Click Save and Restart.

From the Admin Web UI

  1. Click Access Controls.

    • The Group and User Access Rules tab displays.

  2. Click the Global Access Rules tab.

  3. Confirm the global domain rule appears under Domains.

From the CLI

  1. Connect to your console and get root privileges.

  2. 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
        }
      ]
  3. Note the id value (in this example, 1).

  4. List the rules in the ruleset:

    sacli --ruleset_id '1'1 AccessControlRulesList

    1

    Replace the ruleset_id value 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.

  1. Connect a VPN client to the server.

  2. On the Access Server, start a packet capture:

    tcpdump -eni any icmp
  3. 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.com is 192.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/10 by 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.

In this step, you verify that firewall rules were created correctly for domain routing. The expected mappings are:

  • Real IP: 192.0.2.1 (app1.example.com)

  • Mapped internal IP: 100.64.0.1

Verify rules using nftables

  • On the Access Server, run:

    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 traffic from the VPN client IP is marked and DNATed from the mapped IP (100.64.0.1) to the real application IP (192.0.2.1).

Verify rules using iptables

You can verify the same domain routing rules using either of the following commands.

  1. Display the rules in the domain routing chain:

    iptables -t nat -S AS0_DOMAIN_RT
    
    • Example output:

      -N AS0_DOMAIN_RT
      -A AS0_DOMAIN_RT -s 172.27.232.2/32 -d 100.64.0.1/32 -j MARK --set-xmark 0x8000000/0x8000000
      -A AS0_DOMAIN_RT -s 172.27.232.2/32 -d 100.64.0.1/32 -j DNAT --to-destination 192.0.2.1
  2. Alternatively, view the rules with counters and line numbers:

    iptables -t nat -L AS0_DOMAIN_RT -n -v --line-numbers
    • Example output:

      Chain AS0_DOMAIN_RT (1 references)
      num   pkts bytes target     prot opt in     out     source               destination
      1        1    60 MARK       0    --  *      *       172.27.232.2         100.64.0.1           MARK or 0x8000000
      2        1    60 DNAT       0    --  *      *       172.27.232.2         100.64.0.1           to:192.0.2.1
  3. These outputs confirm that the domain routing rule for app1.example.com has been correctly applied at the firewall level.

Step-by-Step: Scenario 2 — Domain routing with group-based access

We'll create separate rules for the Sales and Support groups.

Sales group

  1. Sign in to the Admin Web UI.

  2. Click Groups and select Sales.

  3. Click the Access Rules tab.

  4. Click New Access Rule.

  5. In the Address field, enter a domain:

    app2.example.com
    

    Note

    Ensure you use an exact domain.

  6. Select NAT as the destination type.

  7. Observe that the Protocol and Port fields are disabled when a domain is entered.

  8. Click Save rule and Restart.

Support group

Repeat the same steps for the Support group, using:

app3.example.com

From the Admin Web UI

  1. Click Access Controls.

    • The Group and User Access Rules tab is displayed.

  2. Confirm that each domain appears correctly in the Destination column for the corresponding group.

From the CLI

  1. Connect to the console and get root privileges.

  2. 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
        }
      ]
      
  3. Identify the ruleset IDs for the Sales and Support groups.

  4. 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"
        }
      ]
  5. Verify that:

    • Sales has a rule for app2.example.com.

    • Support has a rule for app3.example.com.

  1. Start tcpdump on Access Server:

    tcpdump -eni any icmp
  2. 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.com is 192.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/10 by default).

    • This mapping ensures traffic is routed through the VPN tunnel.

  3. 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.com is 192.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/10 by default).

    • This mapping ensures traffic is routed through the VPN tunnel.

  4. The Access Server tcpdump outputs 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.

In this step, you verify that firewall rules were created correctly for domain routing and group-based access.

The expected mappings are:

  • Sales group

    • Real IP: 192.0.2.2 (app2.example.com)

    • Mapped internal IP: 100.64.0.2

  • Support group

    • Real IP: 192.0.2.3 (app3.example.com)

    • Mapped internal IP: 100.64.0.3

Verify rules using nftables

  • On the Access Server, run:

    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.

Verify rules using iptables

You can verify the same domain routing rules using either of the following commands.

  1. Display the rules in the domain routing chain:

    iptables -t nat -S AS0_DOMAIN_RT
    • Example output:

      -N AS0_DOMAIN_RT
      -A AS0_DOMAIN_RT -s 172.27.240.2/32 -d 100.64.0.2/32 -j MARK --set-xmark 0x8000000/0x8000000
      -A AS0_DOMAIN_RT -s 172.27.240.2/32 -d 100.64.0.2/32 -j DNAT --to-destination 192.0.2.2
      -A AS0_DOMAIN_RT -s 172.27.248.3/32 -d 100.64.0.3/32 -j MARK --set-xmark 0x8000000/0x8000000
      -A AS0_DOMAIN_RT -s 172.27.248.3/32 -d 100.64.0.3/32 -j DNAT --to-destination 192.0.2.3
  2. Alternatively, view the rules with counters and line numbers:

    iptables -t nat -L AS0_DOMAIN_RT -n -v --line-numbers
    • Example output:

      Chain AS0_DOMAIN_RT (1 references)
      num   pkts bytes target     prot opt in     out     source               destination
      1        1    60 MARK       0    --  *      *       172.27.240.2         100.64.0.2           MARK or 0x8000000
      2        1    60 DNAT       0    --  *      *       172.27.240.2         100.64.0.2           to:192.0.2.2
      3        1    60 MARK       0    --  *      *       172.27.248.3         100.64.0.3           MARK or 0x8000000
      4        1    60 DNAT       0    --  *      *       172.27.248.3         100.64.0.3           to:192.0.2.3
  3. These outputs confirm that domain routing and group-based access rules are correctly applied at the firewall level.