ZTNA SSH access proxy example
ZTNA can be configured with SSH access proxy to provide a seamless SSH connection to the server.
Advantages of using an SSH access proxy instead of a TCP forwarding access proxy include:
-
Establishing device trust context with user identity and device identity checks.
-
Applying SSH deep inspection to the traffic through the SSH related profile.
-
Performing optional SSH host-key validation of the server.
-
Using one-time user authentication to authenticate the ZTNA SSH access proxy connection and the SSH server connection.
Perform SSH host-key validation of the server
To act as a reverse proxy for the SSH server, the FortiProxy must perform SSH host-key validation to verify the identity of the SSH server. The FortiProxy does this by storing the public key of the SSH server in its SSH host-key configurations. When a connection is made to the SSH server, if the public key matches one that is used by the server, then the connection is established. If there is no match, then the connection fails.
One-time user authentication
SSH access proxy allows user authentication to occur between the client and the access proxy, while using the same user credentials to authenticate with the SSH server. The following illustrates how this works:
-
The remote endpoint registers to FortiClient EMS and receives the client certificate.
-
The remote endpoint tries to connect to the SSH access proxy. It must use the same username that is later used for access proxy authentication.
-
The FortiProxy challenges the endpoint with device identity validation.
-
The remote endpoint provides the EMS issued certificate for device identification.
-
The FortiProxy challenges the endpoint with user authentication. For example, this could be done with basic or SAML authentication.
-
The users enters their credentials on the remote endpoint.
-
The FortiProxy authenticates the user and collects the username.
-
Using the FortiProxy's CA or the customer's CA certificate, the FortiProxy signs an SSH certificate and embeds the username in its principal.
-
The FortiProxy attempts to connect to the SSH server using the certificate authentication.
-
The SSH server verifies the authenticity of the certificate, and matches the username principal against its authorized_keys file.
-
If the username matches a record in the file, then the SSH connection is established. If no match is found, then the SSH connection fails.
Example
In this example, an SSH connection is established using SSH access proxy with host-key validation and one-time authentication.
-
The SSH server is a Linux based server that uses sshd to provide remote access
-
For SSH host-key validation, the public key of the SSH server has been imported into the FortiProxy.
-
For one-time authentication using certificate authentication:
-
The SSH server must allow certificate authentication.
-
The SSH server must have the proper entry in its authorized_keys file that contains the user principal and the FortiProxy CA's public key.
-
The entry is present in the user directory corresponding to the user that is trying to log in.
-
To pre-configure the Linux SSH server:
-
Retrieve the public key used for host-key validation:
-
Locate the public key files in the SSH server:
$ ls -la /etc/ssh/*.pub -rw-r--r-- 1 root root 186 Mar 29 2020 /etc/ssh/ssh_host_ecdsa_key.pub -rw-r--r-- 1 root root 106 Mar 29 2020 /etc/ssh/ssh_host_ed25519_key.pub -rw-r--r-- 1 root root 406 Mar 29 2020 /etc/ssh/ssh_host_rsa_key.pub2
-
Choose the public key file based on the hash type (in this case, ECDSA), and show it's content:
$ cat /etc/ssh/ssh_host_ecdsa_key.pub ecdsa-sha2-nistp256 AAAAE2*********IpEik=
This key will be used when configuring the FortiProxy.
-
-
Retrieve the FortiProxy CA’s public key from the FortiProxy:
# show full firewall ssh local-ca Fortinet_SSH_CA config firewall ssh local-ca edit "Fortinet_SSH_CA" set password ENC <hidden password> set private-key "-----BEGIN OPENSSH PRIVATE KEY----- <hidden private key> -----END OPENSSH PRIVATE KEY-----" set public-key "ssh-rsa AAAAB3**********JLXlxj3” set source built-in next end
-
On the Linux server, enable the SSH service to use the authorized_keys file:
-
Locate and edit the /etc/ssh/sshd_config file.
-
Ensure that the AuthorizedKeysFile line is uncommented, for example:
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
-
-
Allow remote SSH log in with certificate authentication and principal name:
-
Log in to the SSH server using the account that will be granted remote SSH access (in this example: sshtest):
-
Locate the account's authorized_keys file in the ~/.ssh directory:
$ ls -la ~/.ssh total 12 drwxrwxr-x 2 sshtest sshtest 4096 Aug 10 19:14 . drwxr-xr-x 5 sshtest sshtest 4096 Aug 10 19:13 .. -rw-rw-r-- 1 sshtest sshtest 419 Aug 10 19:14 authorized_keys
-
If the directory and file do not exist, create the directory:
$ mkdir ~/.ssh
-
Create an entry containing the following keywords and add them to the authorized_keys file:
echo 'cert-authority,principals="sshtest" ssh-rsa AAAAB3**********JLXlxj3' >> authorized_keys
Where:
-
cert-authority
- indicates that this entry is used in certificate authentication by validating the certificate using the public key provided in this entry. -
principals="sshtest"
- indicates the user that must match with the username embedded in the SSH certificate. -
ssh-rsa AAAAB3**********JLXlxj3
- indicates the FortiProxy CA’s public key that is used to validate the SSH certificate.
-
-
-
Restart the sshd service:
$ sudo systemctl stop sshd $ sudo systemctl start sshd
The SSH server can now accept SSH connection from sshtest@<server IP>, where the SSH certificate used by the FortiProxy to log in contains sshtest embedded as a principal.
When a user connects from a SSH client using <username>@<server IP>, sshd will locate the authorized_keys file in the directory /home/<username>/.ssh/authorized_keys. If the authorized_keys is not in that directory, authentication will fail on the SSH server side. If you suspect that authentication is failing on the SSH server, use the following commands to manually start sshd in debug mode to troubleshoot: $ sudo systemctl stop sshd $ /usr/sbin/sshd -ddd -p 22 |
To configure the FortiProxy :
-
Configure a new VIP to allow access to the SSH access proxy over 192.168.2.87:443:
config firewall vip edit "ZTNA_SSH" set type access-proxy set extip 10.1.1.13 set extintf "any" set server-type https set extport 7443 set ssl-certificate "Fortinet_SSL" next end
-
Configure the address object for the SSH server:
config firewall address edit "SSH_server" set subnet 10.120.1.79 255.255.255.255 next end
-
Configure the host-key that will be used to authenticate the SSH server. The public-key was retrieved when pre-configure the Linux SSH server (step 1b).
config firewall ssh host-key edit "ed25519" set type ECDSA set usage access-proxy set public-key "AAAAE2**********IpEik=" next end
-
Configure the access proxy SSH client certificate:
A CA certificate is assigned to sign the SSH certificate that will be used in the SSH authentication. The SSH certificate will have the username embedded in the certificate principal.
config firewall access-proxy-ssh-client-cert edit "ssh-access-proxy" set source-address enable set auth-ca "Fortinet_SSH_CA" next end
-
Configure the access-proxy server setting:
config firewall access-proxy edit "ZTNA_SSH" set vip "ZTNA_SSH" set client-cert enable config api-gateway edit 1 set url-map "tcp" set service tcp-forwarding config realservers edit 1 set address "SSH_server" set type ssh set ssh-client-cert "ssh-access-proxy" set ssh-host-key-validation enable set ssh-host-key "ed25519" next end next end next end
-
Configure the user setting, and user group to apply user authentication to the access proxy connection using local-user-db:
config user local edit ""sshtest" set type password set passwd-time 2024-09-11 13:05:32 set passwd ********** next end config user group edit "test-grp" set member "sshtest" next end
-
Create the authentication scheme and rule to perform the authentication:
config authentication scheme edit "scheme-basic" set method basic set user-database "local-user-db" next end config authentication rule edit "rule-basic" set srcintf "any" set srcaddr "all" set dstaddr "all" set active-auth-method "scheme-basic" next end
-
Configure the full ZTNA policy to allow traffic to the SSH server, and apply user authentication, posture check, and a security profile where necessary:
config firewall policy edit 3 set type access-proxy set name "SSH-proxy" set uuid ba5687be-6fa2-51ef-a6be-59326c02ad24 set srcintf "any" set srcaddr "all" set dstaddr "all" set action accept set schedule "always" set access-proxy "ZTNA_SSH" set ztna-ems-tag "EMS1_ZTNA_win10" set logtraffic all set log-http-transaction enable set extended-log enable set groups "test-grp" next end
To check the results:
-
On the remote client, open FortiClient, go to the Zero Trust Telemetry tab, and make sure that it is connected to the EMS server.
-
Go to the ZTNA Destination tab and click Add Destination.
-
Configure the Destination, then click Create:
Rule Name
SSH-Linux
Destination Host
10.120.1.79:22
Proxy Gateway
10.1.1.13:7443
Mode
Transparent
Encryption
Disabled (recommended)
When Encryption is disabled, the connection between the client and FortiProxy application gateway is not encapsulated in HTTPS after the client and FortiProxy connection is established. This allows for less overhead, because SSH is already a secure connection.
-
Open an SSH client, such as PuTTy, and make an SSH connection to sshtest@10.120.1.79 on port 22.
-
After device authentication is performed and passes in the background, FortiClient prompts the user to sign in. Enter the username, sshtest, and password, then click Sign in.
After successful user authentication, the SSH connection is established without an additional log in.
-
On the FortiProxy, check the logged in user:
-
Go to Dashboard > > User & Devices > User Monitor.
-
Check the WAD proxy user list:
# diagnose wad user list ID: 22, VDOM: root, IPv4: 10.100.1.32 user name : sshtest worker : 0 duration : 824 seconds auth_type : IP auth_method : Basic pol_id : 3 g_id : 2 user_based : 0 expire : N/A (in use) LAN: bytes_in=5711 bytes_out=35720 WAN: bytes_in=2617 bytes_out=3377
-
-
The successful connection is logged in the forward traffic logs after the SSH connection has disconnected:
# execute log display 25 logs found. 10 logs returned.
date=2024-09-11 time=13:13:12 eventtime=1726085591891200442 tz="-0700" logid="0005000024" type="traffic" subtype="ztna" level="notice" vd="root" srcip=10.100.1.32 srcport=53562 srcintf="port1" srcintfrole="undefined" dstcountry="Reserved" srccountry="Reserved" dstip=10.120.1.79 dstport=22 dstintf="port1" dstintfrole="undefined" sessionid=598330087 service="SSH" proxyapptype="http" proto=6 action="accept" policyid=3 policytype="proxy-policy" poluuid="ba5687be-6fa2-51ef-a6be-59326c02ad24" policyname="SSH-proxy" clientip=10.100.1.32 duration=564 user="sshtest" group="test-grp" gatewayid=1 vip="ZTNA_SSH" accessproxy="ZTNA_SSH" clientdeviceid="F0D60B28FCAB464E81C725270B62BEC0" clientdevicemanageable="manageable" clientdevicetags="MAC_EMS1_ZTNA_win10/MAC_EMS1_ZTNA_Anti_Virus/EMS1_ZTNA_Anti_Virus/MAC_EMS1_ZTNA_all_registered_clients" emsconnection="online" wanin=0 rcvdbyte=0 wanout=0 lanin=1890 sentbyte=1890 lanout=1865 fctuid="F0D60B28FCAB464E81C725270B62BEC0" unauthuser="userb" unauthusersource="forticlient" srcremote=207.102.138.19 appcat="unscanned"