{"id":79,"date":"2018-04-25T16:43:58","date_gmt":"2018-04-25T16:43:58","guid":{"rendered":"https:\/\/tog000.io\/?p=79"},"modified":"2018-04-25T16:43:58","modified_gmt":"2018-04-25T16:43:58","slug":"managing-ssh-tunnels-running-in-the-background","status":"publish","type":"post","link":"https:\/\/gtrisca.dev\/index.php\/2018\/04\/25\/managing-ssh-tunnels-running-in-the-background\/","title":{"rendered":"Managing SSH tunnels running in the background"},"content":{"rendered":"<p>A common problem for me when setting up SSH tunnels is that even though the ssh client process is running, data is not going through.<\/p>\n<p>Steps to reproduce:<\/p>\n<ul>\n<li>Create a tunnel (<span class=\"lang:default decode:true crayon-inline \">ssh -D<\/span>\u00a0 or\u00a0<span class=\"lang:default decode:true crayon-inline \">ssh -L<\/span>\u00a0 or <span class=\"lang:default decode:true crayon-inline \">ssh -R<\/span>\u00a0) on some port<\/li>\n<li>Data is not going through, so we need to restart it<\/li>\n<li>The connection cannot be established because <span class=\"lang:default highlight:0 decode:true crayon-inline\">bind: Address already in use<\/span><\/li>\n<li>We have to kill the old client, <span class=\"lang:default decode:true crayon-inline \">ps aux | grep ssh<\/span>\u00a0, to find the right\u00a0 process and then <span class=\"lang:default decode:true crayon-inline \">kill -9<\/span>\u00a0 it<\/li>\n<li>Re-create the tunnel<\/li>\n<\/ul>\n<p>Instead, we could leverage sockets when creating the connection, which allow communication with the SSH process (as opposed to searching for the <span class=\"lang:default decode:true  crayon-inline \">pid<\/span>\u00a0). This is enabled by the\u00a0-S option:<\/p>\n<pre class=\"nums:false lang:default decode:true\" title=\"start_proxy.sh\">ssh -NMfn -S \/tmp\/server1.local.socket -o ExitOnForwardFailure=yes -D 8080 server1.local \r\n\r\n# Additional flags: \r\n# -N Don't open a terminal\r\n# -M Master mode, necessary for socket commands\r\n# -f Go to background\r\n# -S Control socket<\/pre>\n<p>Once the socket is set up, we can send commands to it. For example,\u00a0<span class=\"lang:default decode:true crayon-inline \">exit<\/span>\u00a0 to close the connection (regardless of the <em>state<\/em> of the connection):<\/p>\n<pre class=\"nums:false lang:default decode:true\" title=\"stop_proxy.sh\">ssh -S \/tmp\/server1.local.socket -O exit server1.local<\/pre>\n<p>Finally, here is a\u00a0script that will create SOCKS tunnels (proxies) to a list of hostnames. When the script is run again, it will attempt to close any existing tunnels and establish brand new connections:<\/p>\n<pre class=\"nums:false lang:zsh mark:4-5 decode:true\" title=\"create_proxy.sh\">#!\/bin\/bash\r\n\r\n\r\n# These are the servers that we will set up SOCKS tunnels to\r\nHOSTS=\"server1.local server2.remote\"\r\nBASE_PORT=11000\r\n\r\n# Some fancy output\r\nbold=$(tput bold)\r\nnormal=$(tput sgr0)\r\n\r\n# Send exit to all existing sockets\r\nfor HOST in $HOSTS; do\r\n  if [ -e \/tmp\/$HOST.socket ]; then\r\n    ssh -S \/tmp\/$HOST.socket -O exit $HOST\r\n  fi\r\ndone\r\n\r\n# Set up variables and nice output\r\nPORT=$BASE_PORT\r\nSTATUS_LINE=\"%-35s%-15s${bold}%s${normal}\"\r\nprintf \"${bold}$STATUS_LINE\\n${normal}\" \"HOST\" \"SOCKS PORT\" \"STATUS\"\r\nfor HOST in $HOSTS; do\r\n  printf \"$STATUS_LINE\" \"$HOST\" \"$PORT\" \"CONNECTING\"\r\n  # Attempt to create tunnel\r\n  ssh -NMfn -S \/tmp\/$HOST.socket -o ConnectTimeout=5 -o ExitOnForwardFailure=yes -D $PORT $HOST &amp;&gt; \/dev\/null\r\n  # Report outcome\r\n  if (( $? == 0 )); then\r\n    printf \"\\r$STATUS_LINE\\n\" \"$HOST\" \"$PORT\" \"DONE      \"\r\n  else\r\n    printf \"\\r$STATUS_LINE\\n\" \"$HOST\" \"$PORT\" \"FAILED    \"\r\n  fi\r\n\r\n  # Increment port number\r\n  PORT=$(expr $PORT + 1)                                                                                                                                                                                                                     \r\ndone<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A common problem for me when setting up SSH tunnels is that even though the ssh client process is running, data is not going through. Steps to reproduce: Create a tunnel (ssh -D\u00a0 or\u00a0ssh -L\u00a0 or ssh -R\u00a0) on some port Data is not going through, so we need to restart it The connection cannot [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10],"tags":[14,12,11,13],"_links":{"self":[{"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/posts\/79"}],"collection":[{"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/comments?post=79"}],"version-history":[{"count":6,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/posts\/79\/revisions"}],"predecessor-version":[{"id":85,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/posts\/79\/revisions\/85"}],"wp:attachment":[{"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/media?parent=79"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/categories?post=79"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gtrisca.dev\/index.php\/wp-json\/wp\/v2\/tags?post=79"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}