{"id":153,"date":"2016-05-07T08:32:42","date_gmt":"2016-05-07T06:32:42","guid":{"rendered":"https:\/\/linuxundich.de\/en\/ssh-tips-changed-host-keys-killing-and-parking-connections\/"},"modified":"2016-05-07T08:32:42","modified_gmt":"2016-05-07T06:32:42","slug":"ssh-tips-changed-host-keys-killing-and-parking-connections","status":"publish","type":"post","link":"https:\/\/linuxundich.de\/en\/ssh-tips-changed-host-keys-killing-and-parking-connections\/","title":{"rendered":"SSH Tips: Changed Host Keys, Killing and Parking Connections"},"content":{"rendered":"\n<p class=\"dropcapp wp-block-paragraph\">If you like tinkering with the Raspberry Pi or other single-board computers such as the Banana Pi, Odroid and the like, you keep running into SSH. The images made for these mini computers are usually based on Linux and therefore mostly come with SSH access built in. In everyday tinkering, however, you set these machines up from scratch again and again, or you quickly pull the power plug to &#8220;just&#8221; restart the device. That throws SSH off balance: after installing a new system, the stored SSH key no longer matches, or the SSH client hangs when you suddenly pull the plug. You can solve these problems the quick and dirty way, but there is always a clean way, too.<\/p>\n\n<!--more-->\n\n<p class=\"wp-block-paragraph\">When establishing a connection via SSH, the SSH client usually stores the public SSH key of the remote system together with its hostname and IP address in the file <code>~\/.ssh\/known_hosts<\/code> in the current user&#8217;s home directory on the client machine. Among other things, this is done to prevent <a href=\"https:\/\/en.wikipedia.org\/wiki\/Man-in-the-middle_attack\">man-in-the-middle attacks<\/a>, in which an attacker pretends to be the target machine in order to phish your login credentials. However, this security measure also kicks in when there is no threat at all: for example, when you set up a Pi from scratch and try to log in via SSH again. In such a case, SSH reports <code>WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED<\/code> in big letters.<\/p>\n\n<h2 class=\"wp-block-heading\">SSH after reinstalling the system<\/h2>\n\n<pre class=\"wp-block-preformatted\">$ <strong>grep 192.168.111.100 ~\/.ssh\/known_hosts<\/strong>\nraspberrypi,192.168.111.100 ecdsa-sha2-nistp256 AAAAE2...ABBBBqf<\/pre>\n\n<pre class=\"wp-block-preformatted\">$ <strong>ssh pi@192.168.111.100<\/strong>\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\nSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\nIt is also possible that a host key has just been changed.\nThe fingerprint for the ECDSA key sent by the remote host is\nSHA256:6rR+0\/i3KnPLds3EuGkfWiudIgu8VMpe1xq+X3I3yNM.\nPlease contact your system administrator.\nAdd correct host key in \/home\/toff\/.ssh\/known_hosts to get rid of this message.\nOffending ECDSA key in \/home\/toff\/.ssh\/known_hosts:10\nECDSA host key for 192.168.111.100 has changed and you have requested strict checking.\nHost key verification failed.<\/pre>\n\n<p class=\"wp-block-paragraph\">You could now open the file <code>~\/.ssh\/known_hosts<\/code> in a text editor and delete the offending line 10 from the list by hand, but there is a better way: with <code>ssh-keygen -R IP-address<\/code>, you remove the key from the file with a single command, so the next time you connect, you start from scratch \u2013 and have to confirm the key just like the very first time you connected to this machine. This also works if you use the hostname instead of the IP address to connect. To be on the safe side, the command copies the old state to <code>~\/.ssh\/known_hosts.old<\/code> in the same directory.<\/p>\n\n<pre class=\"wp-block-preformatted\">$ <strong>ssh-keygen -R 192.168.111.100<\/strong>\n# Host 192.168.111.100 found: line 10\n\/home\/toff\/.ssh\/known_hosts updated.\nOriginal contents retained as \/home\/toff\/.ssh\/known_hosts.old<\/pre>\n\n<pre class=\"wp-block-preformatted\">$ <strong>ssh pi@192.168.111.100<\/strong>\nThe authenticity of host 'raspberrypi (192.168.111.100)' can't be established.\nECDSA key fingerprint is SHA256:6rR+0\/i3KnPLds3EuGkfWiudIgu8VMpe1xq+X3I3yNM.\nAre you sure you want to continue connecting (yes\/no)? yes\nWarning: Permanently added '192.168.111.100' (ECDSA) to the list of known hosts.\npi@192.168.111.100's password:\n\nThe programs included with the Debian GNU\/Linux system are free software;\nthe exact distribution terms for each program are described in the\nindividual files in \/usr\/share\/doc\/*\/copyright.\n\nDebian GNU\/Linux comes with ABSOLUTELY NO WARRANTY, to the extent\npermitted by applicable law.\nLast login: Fri Apr 22 08:40:10 2016 from 192.168.178.57<\/pre>\n\n<h2 class=\"wp-block-heading\">Forcibly terminating an SSH connection<\/h2>\n\n<p class=\"dropcapp wp-block-paragraph\">If you are logged in to a remote machine via SSH and shut it down with <code>shutdown<\/code>, <code>halt<\/code> or <code>reboot<\/code>, the system doesn&#8217;t kill the SSH connection abruptly. It stops the SSH server cleanly during shutdown, so you end up back in the terminal of the client machine and can keep working in the same terminal window. Now, I \u2013 and surely other Pi tinkerers too \u2013 like to unplug the Raspberry Pi and plug it back in to restart it quickly and painlessly. This is certainly not ideal for the integrity of the data on the memory card, but if I&#8217;m going to set up the system on it from scratch anyway, I don&#8217;t much care.<\/p>\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ac599ed22fda&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ac599ed22fda\" class=\"wp-block-image wp-lightbox-container\"><img decoding=\"async\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/linuxundich.de\/wp-content\/uploads\/2016\/05\/raspberry-pi-ssh-steuercodes.png\" alt=\"SSH connections can be managed with a set of escape sequences.\" style=\"width:100%\"\/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">SSH connections can be managed with a set of escape sequences.<\/figcaption><\/figure>\n\n<p class=\"wp-block-paragraph\">The downside is that SSH usually hangs in the terminal when you do this \u2013 after all, you just pulled the chair out from under it. You could now kill the SSH process or close the terminal window and open it again, but there is a clean solution for this situation, too: SSH knows a number of escape sequences that let you manage the current SSH session. You get an overview of the available commands if you type <code>~?<\/code> on a new line in the terminal. To be on the safe side, simply press Enter once beforehand.<\/p>\n\n<pre class=\"wp-block-preformatted\">pi@raspberrypi:~ # <strong>~?<\/strong>\nSupported escape sequences:\n ~.   - terminate connection (and any multiplexed sessions)\n ~B   - send a BREAK to the remote system\n ~C   - open a command line\n ~R   - request rekey\n ~V\/v - decrease\/increase verbosity (LogLevel)\n ~^Z  - suspend ssh\n ~#   - list forwarded connections\n ~&amp;   - background ssh (when waiting for connections to terminate)\n ~?   - this message\n ~~   - send the escape character by typing it twice\n(Note that escapes are only recognized immediately after newline.)<\/pre>\n\n<p class=\"wp-block-paragraph\">The first sequence shown in the help is exactly the function we&#8217;re looking for: if you type <code>~.<\/code> as text during an SSH session, you terminate the current SSH connection, no matter what. This doesn&#8217;t only work with a session that is still active and working (which you could close with <code>exit<\/code> at any time anyway), but also when, for example, you cut the power to the Pi and nothing happens in the terminal anymore. Here, too, it can help to press Enter once more before the actual command. Otherwise the escape sequence may come to nothing.<\/p>\n\n<h2 class=\"wp-block-heading\">Pausing and resuming an SSH connection<\/h2>\n\n<p class=\"dropcapp wp-block-paragraph\">The escape sequences can do other handy things, too. For example, you can suspend an SSH connection and resume it later without having to use a terminal multiplexer such as <code>screen<\/code> or <code>tmux<\/code>. If a process takes longer than expected, you can park the connection this way while the process on the remote machine keeps running. Unlike with the two terminal multiplexers mentioned, you don&#8217;t have to think ahead that the task might take longer and start them as a precaution. The corresponding sequence is the somewhat cryptic <code>~^Z<\/code>, where the caret doesn&#8217;t stand for a character but for the Ctrl key. So you type <kbd>~<\/kbd> and then press <kbd>Ctrl<\/kbd>+<kbd>Z<\/kbd>. You then land back in the terminal of the machine on which you originally ran <code>ssh<\/code>. From there, you can pick up the connection again by typing <code>fg<\/code> and pressing Enter.<\/p>\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6ac599ed235e4&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6ac599ed235e4\" class=\"wp-block-image wp-lightbox-container\"><img decoding=\"async\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/linuxundich.de\/wp-content\/uploads\/2016\/05\/ssh-raspberry-pi-suspend.png\" alt=\"Pausing and resuming an SSH connection.\" style=\"width:100%\"\/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Pausing and resuming an SSH connection.<\/figcaption><\/figure>\n\n<p class=\"wp-block-paragraph\">If you work on a &#8220;truly&#8221; remote system over the internet, the connection may well drop. On the one hand, this is because the server terminates the connection after a period of inactivity; on the other hand, your own network infrastructure (read: the router) may interfere. However, you can prevent the timeout with a keep-alive function. Depending on the situation, you can either configure the SSH server accordingly (which of course requires root privileges) or call SSH with the appropriate parameters right away. In that case, you don&#8217;t need any special privileges on either system.<\/p>\n\n<h3 class=\"wp-block-heading\">Keep-alive on the server side<\/h3>\n\n<pre class=\"wp-block-preformatted\">### Default keep-alive settings:\n$ <strong>grep Alive \/etc\/ssh\/sshd_config<\/strong>\n#TCPKeepAlive yes\n#ClientAliveInterval 0\n#ClientAliveCountMax 3\n### Edit the SSH server configuration:\n$ <strong>sudo nano \/etc\/ssh\/sshd_config<\/strong>\n\n### In the end, the relevant lines should look like this:\n$ <strong>grep Alive \/etc\/ssh\/sshd_config<\/strong>\nTCPKeepAlive yes\nClientAliveInterval 60\nClientAliveCountMax 3\n\n### Restart the SSH server once:\n$ <strong>sudo systemctl restart sshd<\/strong><\/pre>\n\n<h3 class=\"wp-block-heading\">Keep-alive on the client side<\/h3>\n\n<pre class=\"wp-block-preformatted\">### Keep the SSH connection alive from the client side\n$ <strong>ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=1 pi@raspberrypi<\/strong><\/pre>\n\n<p class=\"wp-block-paragraph\">In the first case, the setting applies to all users who want to log in to the system via SSH. As a rule, you should therefore only make this change if all users actually need it. Most of the time, though, you only need keep-alive in exceptional cases, so it makes sense to set the option only when needed when calling <code>ssh<\/code>. For me, this is the case with a web service I can log in to via SSH, for example. If I start long-running backups there, my router terminates the connection before the backup process can report success. With the keep-alive settings mentioned above, however, that&#8217;s no longer a problem.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>SSH tips: remove changed host keys with ssh-keygen -R, kill hung connections and park sessions.<\/p>\n","protected":false},"author":2,"featured_media":157,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"lui_source_id":39416,"lui_source_hash":"ee52307882091e69f66ea9735d27f7ed925f6340865d67730060865fc0dc0de4","lui_source_translated":"2026-10-06","lui_source_reviewed":true,"lui_via_url":"","lui_via_label":"","lui_source_url":"","lui_source_label":"","footnotes":""},"categories":[2],"tags":[],"class_list":["post-153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gnu-linux"],"_links":{"self":[{"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/posts\/153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/comments?post=153"}],"version-history":[{"count":0,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/posts\/153\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/media\/157"}],"wp:attachment":[{"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/media?parent=153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/categories?post=153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/linuxundich.de\/en\/wp-json\/wp\/v2\/tags?post=153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}