{"id":1929,"date":"2019-05-03T16:10:43","date_gmt":"2019-05-03T21:10:43","guid":{"rendered":"http:\/\/www.kickflop.net\/blog\/?p=1929"},"modified":"2019-05-03T16:10:43","modified_gmt":"2019-05-03T21:10:43","slug":"openssh-session-timeouts","status":"publish","type":"post","link":"https:\/\/www.kickflop.net\/blog\/2019\/05\/03\/openssh-session-timeouts\/","title":{"rendered":"OpenSSH Session Timeouts"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">It is often desirable to terminate SSH sessions after they have been sitting idle for a period of time. If you do any quick searching you will find that many (most?) believe that the sshd configuration settings <code>ClientAliveInterval<\/code> and <code>ClientAliveCountMax<\/code> are the place to configure this. Sadly, many security hardening guides[<a href=\"https:\/\/www.stigviewer.com\/stig\/red_hat_enterprise_linux_7\/2017-07-08\/finding\/V-72237\">1<\/a>,<a href=\"https:\/\/cisofy.com\/compliance\/pci-dss\/pci-dss-8-1-8-session-idle-timeout\/\">2<\/a>], frameworks, benchmark documents, and tools (which are based on those documents) provide this same incorrect guidance. The <code>ClientAliveInterval<\/code> and <code>ClientAliveCountMax<\/code> do not at all exist for the sake of the terminating sessions after mere lack of use for a period of time. These settings in OpenSSH are used to determine <em>unresponsive<\/em> clients (NOT responsive\/functioning but idle clients). The settings are used purely as a <em>heartbeat<\/em> mechanism.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below you can see a <code>ClientAliveInterval<\/code> setting of 60 seconds and my OpenSSH session having zero input or output for 120 seconds and still remaining connected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[jblaine@testbed1~]$ sudo grep -i client \/etc\/ssh\/sshd_config\nClientAliveCountMax 0\nClientAliveInterval 60\n[jblaine@testbed1~]$ count=0; while :; do count=$(( count + 120 )); sleep 120; echo $count seconds have passed; done\n120 seconds have passed\n240 seconds have passed\n^C<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Likewise, we see the same behavior with <code>ClientAliveMaxCount<\/code> set to 1:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[jblaine@testbed1~]$ sudo grep -i client \/etc\/ssh\/sshd_config\nClientAliveCountMax 1\nClientAliveInterval 60\n[jblaine@testbed1~]$ count=0; while :; do count=$(( count + 120 )); sleep 120; echo $count seconds have passed; done\n120 seconds have passed\n240 seconds have passed\n^C<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSSH has zero functionality built into it to disconnect sessions that are <em>functional<\/em> but merely idle for a certain period of time. When sshd receives no response from a client after <code>ClientAliveMaxCount * ClientAliveInterval<\/code> seconds, it means we are considering the client <em>unresponsive network-wise<\/em> and sshd will terminate connection. See <code>client_alive_check()<\/code> in <a href=\"https:\/\/github.com\/openssh\/openssh-portable\/blob\/master\/serverloop.c\">OpenSSH serverloop.c<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">How did this misunderstanding come about? The usual suspects: Echo chambers and people copying and pasting without testing. But I also blame the <code>ClientAliveInterval<\/code> section of the man page for <code>sshd<\/code> which uses the overloaded term &#8220;inactive&#8221; where it should use the word &#8220;unresponsive&#8221;. As such, I&#8217;ve created a <a href=\"https:\/\/github.com\/openssh\/openssh-portable\/pull\/129\">pull request<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is often desirable to terminate SSH sessions after they have been sitting idle for a period of time. If&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[51,35,9,44,11,13,48],"tags":[54,57,58,53,56,59,55],"class_list":["post-1929","post","type-post","status-publish","format-standard","hentry","category-devops","category-linux","category-musings","category-security","category-sysadmin","category-tips","category-unixlinux","tag-cis","tag-infosec","tag-linux","tag-openssh","tag-security","tag-sshd","tag-stig"],"_links":{"self":[{"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/posts\/1929","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/comments?post=1929"}],"version-history":[{"count":7,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/posts\/1929\/revisions"}],"predecessor-version":[{"id":1936,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/posts\/1929\/revisions\/1936"}],"wp:attachment":[{"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/media?parent=1929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/categories?post=1929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kickflop.net\/blog\/wp-json\/wp\/v2\/tags?post=1929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}