FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
ojacinto
Staff
Staff
Article Id 362819
Description This article describes the behavior by design for allowed existing sessions after the ZTNA tag is removed on FortiGate and how to block the traffic once the ZTNA tag has been removed.
Scope FortiGate v7.2.0 and later, v7.4.0 and later.
Solution

When using ZTNA telemetry, tags, and policy enforcement, ZTNA tags are synchronized with the FortiGate in real-time.
FortiGate uses tags to grant access based on the ZTNA tags applied in the ZTNA rule.

 

On versions previous to 7.2.0, after a ZTNA tag was removed from a device, if there was an existing session (like extended ping, RDP, or SSH connection) this original session remained active even when the tag was removed on the endpoint.

 

On the FortiGate side, it was confirmed that tag information was properly updated and it was not matching the test endpoint however, existing sessions remained active.

 

Example:

  • When a client (endpoint) authenticates, it receives the ZTNA tags, then the dynamic object on FortiGate is updated.
    Endpoint traffic is correctly allowed according to ZTNA tag rules.
  • Upon the client logging off or disconnected from the EMS server, the dynamic object is updated to the FortiGate as expected and the endpoint IP address is no longer associated with the dynamic object.
  • Despite this last condition, traffic (existing sessions) remains allowed until the FortiGate rules are forced to refresh or the session is cleared, unlike new sessions which are blocked correctly.

 

FW-FGT-VM # diag firewall dynamic list EMS_ZTNA_APP_SERVERS
CMDB name: EMS_ZTNA_APP_SERVERS
TAG name: APP_SERVERS
EMS_ZTNA_APP_SERVERS: ID(115)
ADDR(192.168.30.47)
ADDR(192.168.30.35)
ADDR(192.168.30.108) < ---
ADDR(192.168.30.126)
Total IP dynamic range blocks: 0.
Total IP dynamic addresses: 4.

 

FW-FGT-VM # get system session list | grep 192.168.30.108
icmp 45 192.168.30.108:8 - 172.16.25.100:8 -


One SSH session is first established successfully when the client matches the firewall policy tag-checking:

 

FW-FGT-VM # diagnose sys session list
session info: proto=6 proto_state=01 duration=96 expire=3545 timeout=0 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ helper=dns-udp vlan_cos=0/255
state=log may_dirty f00
statistic(bytes/packets/allow_err): org=73/1/1 reply=261/1/1 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=9->3/3->9 gwy=192.168.170.1/0.0.0.0
hook=post dir=org act=noop 192.168.30.108:54225->192.168.12.99:22(0.0.0.0:0)
hook=pre dir=reply act=noop 192.168.12.99:22->192.168.30.108:54225
misc=0 policy_id=3 pol_uuid_idx=15849 auth_info=0 chk_client_info=0 vd=0
serial=000fb1fd tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=80000000 ngfwid=n/a
npu_state=0x000100
no_ofld_reason: npu-flag-off
total session 1


FW-FGT-VM # get system session list | grep 192.168.12.99
tcp 3556 192.168.30.108:54225 - 192.168.12.99:22 -

 

After the endpoint was disconnected from EMS, tags were removed and this information was updated to the  FortiGate (IP 192.168.30.108 was removed from the dynamic list):

FW-FGT-VM # diag firewall dynamic list EMS_ZTNA_APP_SERVERS
CMDB name: EMS_ZTNA_APP_SERVERS
TAG name: APP_SERVERS
EMS_ZTNA_APP_SERVERS: ID(115)
ADDR(192.168.30.47)
ADDR(192.168.30.35)
ADDR(192.168.30.126)
Total IP dynamic range blocks: 0.
Total IP dynamic addresses: 3.

However, the existing session continues working and traffic from the endpoint to server 192.168.12.99 is alive:

FW-FGT-VM # dia sys session list

session info: proto=6 proto_state=01 duration=709 expire=3540 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ helper=dns-udp vlan_cos=0/255
state=log may_dirty f00
statistic(bytes/packets/allow_err): org=73/1/1 reply=261/1/1 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=9->3/3->9 gwy=192.168.170.1/0.0.0.0
hook=post dir=org act=noop 192.168.30.108:54225->192.168.12.99:22(0.0.0.0:0)
hook=pre dir=reply act=noop 192.168.12.99:22->192.168.30.108:54225
misc=0 policy_id=3 pol_uuid_idx=15849 auth_info=0 chk_client_info=0 vd=0
serial=000fb1fd tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=80000000 ngfwid=n/a
npu_state=0x000100
no_ofld_reason: npu-flag-off

total session 1

FW-FGT-VM # get system session list | grep 192.168.12.99

tcp 3599 192.168.30.108:54225 - 192.168.12.99:22 -


To avoid this behavior and to force the FortiGate to revalidate the live sessions when dynamic address update occurs a new command is introduced 'set dyn-addr-session-check'.

 

config system settings
   set dyn-addr-session-check
       enable<----- Enable dirty session check caused by dynamic address updates.
       disable <----- Disable dirty session check caused by dynamic address updates.
    end

 

After enabling this option when the tag is removed from the endpoint and then updated to FortiGate, the previous session will be marked as 'dirty' and then it will be changed to 'block' after around 10 seconds:

config system settings
    set dyn-addr-session-check enable < ---

end

 

FW-FGT-VM # diag firewall dynamic list EMS_ZTNA_APP_SERVERS
CMDB name: EMS_ZTNA_APP_SERVERS
TAG name: APP_SERVERS
EMS_ZTNA_APP_SERVERS: ID(115)
ADDR(192.168.30.47)
ADDR(192.168.30.35)
ADDR(192.168.30.126)
Total IP dynamic range blocks: 0.
Total IP dynamic addresses: 3.

 

FW-FGT-VM # dia sys session list

session info: proto=6 proto_state=01 duration=1144 expire=3586 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ helper=dns-udp vlan_cos=0/255
state=dirty may_dirty acct-ext
statistic(bytes/packets/allow_err): org=73/1/1 reply=261/1/1 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=9->3/3->9 gwy=192.168.170.1/0.0.0.0
hook=post dir=org act=noop 192.168.30.108:54225->192.168.12.99:22(0.0.0.0:0)
hook=pre dir=reply act=noop 192.168.12.99:22->192.168.30.108:54225
misc=0 policy_id=3 pol_uuid_idx=15849 auth_info=0 chk_client_info=0 vd=0
serial=000fb1fd tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=80000000 ngfwid=n/a
npu_state=0x000100
no_ofld_reason: npu-flag-off
total session 1


FW-FGT-VM # dia sys session list

session info: proto=6 proto_state=01 duration=1155 expire=28 timeout=3600 refresh_dir=both flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ helper=dns-udp vlan_cos=0/255
state=block may_dirty authed acct-ext
statistic(bytes/packets/allow_err): org=73/1/1 reply=261/1/1 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=9->3/3->9 gwy=192.168.170.1/0.0.0.0
hook=post dir=org act=noop 192.168.30.108:54225->192.168.12.99:22(0.0.0.0:0)
hook=pre dir=reply act=noop 192.168.12.99:22->192.168.30.108:54225
misc=0 policy_id=0 pol_uuid_idx=65 auth_info=0 chk_client_info=0 vd=0
serial=000fb1fd tos=ff/ff app_list=0 app=0 url_cat=0
rpdb_link_id=80000000 ngfwid=n/a
npu_state=0x000100
no_ofld_reason: block-by-policy npu-flag-off
total session 1

 

Then endpoint's SSH traffic is blocked.