ssh tunnel 與 autossh

最後更新: 2019-10-02



Local Port Forward (-L)



# 相當於 Local 的 8888 map 成 WWW 的 80

          Client ------------------> Host -------------------> WWW-Server
                        tunnel                 unencrypted
port       8888                       22                        80
        ssh_clinet                ssh_server                    www


ssh -N -f  [username@my_ssh_server] -L [lport]:[remote_host]:[rport]


ssh -NT -f  user@host   -L  8888:WWW-Server:80

  • -N      Do not execute a remote command. (Default "不建立shell")
  • -T      Disable pseudo-tty allocation.
  • -f      "連線後於背景執行"


Reverse ssh tunnel (-R)


一般來說, 這功能是用在 "有出無入" 的地方, 比如 Source 是在 Firewall 後, 而你又想從外面連入去


[SSH_Client] --ssh--[firewall]--ssh--> [SSH_Server(Port:22)]

[SSH_Client] -------[firewall]-------- SSH_Server
(Client Port:22) <---by_pass_fw--- local port:2222


# remote_port:localhost:local_port

ssh -R 2222:localhost:22 user@source


Step_1: 在 firewall 後的 client ssh 出去

Step_2: 成功後, Firewall 外的 Server 的 Port 2222 相當卡 Firewall 後 Server 的 Port 22

 * port 最好用 > 1024, 因為低 port 只有 root 才用到


remote forward(-R) with


Enable GatewayPorts in sshd_config (by default it is disabled)

Enabling it will instruct sshd to allow remote port forwardings to bind to a non-loopback address.


Match User root
   GatewayPorts yes


client cmd

-R 8080:       # 它是指

-R :8080:      # 它是指 !!


openwrt 的 sshd (dropbear)


config dropbear
        option PasswordAuth 'on'
        option RootPasswordAuth 'on'
        option GatewayPorts 'on'
        option Port         '22'


local forward(-L) with


# -g    Allows remote hosts to connect to local forwarded ports.

ssh -g -L 8001:localhost:8000 root@remote-machine

沒有加 "-g" 時

netstat -nlt | grep 8080

tcp        0      0*               LISTEN

加了 "-g"

netstat -nlt | grep 8080

tcp        0      0  *               LISTEN


ssh 時自動建立 tunnel


修改 ~/.ssh/config


# 一行一個 forward
LocalForward [bind_address:]Lport Rhost:Rport


ssh -f -N Lport:Rhost:Rport


putty ssh tunnel


ssh 亦可以作 vpn 之用, 真是不講不知 !!!


工具 pietty:

在 Source port 填 8080

Destination 填


那在 IE 網址填 ,

就可連上綁在 loopback interface 的 Web Server


如果係作 ftp 的 21 加蜜的話, 記得要以 passive mode 登入,

而 server 那裡要有 "pasv_promiscuous=YES" 的設定 (以上是 ftp 的設定)

對比 Linux 上的應用

ssh -f -N -L 2121: root@

-N    不建立shell

-f     連線後執行於背景

以上兩參數缺一不可 !!

SOCKSv5 Proxy

Putty Setting:

Path: Settings -> Connection -> SSH _Tunnels

Source Port: 1080
Destination: BLANK
Type: Dynamic


netstat -an | find "10080"

  TCP              LISTENING

Firefox Setting:

Reverse Tunnel Setting



Disable interactive shell access while tunneling



For any tunnelling-only user, change their login shell to /sbin/nologin



command="/sbin/nologin",no-pty ssh-rsa ...


Match group proxy-only
    ForceCommand /sbin/nologin
    PermitTTY no


# Test by ssh

ssh sshtunnel


PermitTTY no

PTY allocation request failed on channel 0


ForceCommand /sbin/nologin

This account is currently not available.
Connection to SERVER closed.


ChrootDirectory %h

Write failed: Broken pipe


Chroot Tunnel Environment




Proxy Only



Specifies whether TCP forwarding is permitted.

  • 'yes' (the default) or 'all' to allow TCP forwarding,
  • 'no' to prevent all TCP forwarding,
  • 'local' to allow local forwarding only or
  • 'remote' to allow remote forwarding only.


Specifies whether tun(4) device forwarding is allowed

  • yes(permits both point-to-point and ethernet)
  • point-to-point (layer 3)
  • ethernet (layer 2)
  • no (default)


Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.

  • yes (the default) or all to allow StreamLocal forwarding,
  • no to prevent all StreamLocal forwarding,
  • local to allow local (from the perspective of ssh(1)) forwarding only or
  • remote to allow remote forwarding only. 

AllowTcpForwarding remote

AllowStreamLocalForwarding no

GatewayPorts yes


Example: proxy-only


"proxy-only" Group

Match group proxy-only
    X11Forwarding no
    PermitTunnel no
    GatewayPorts yes
    AllowTcpForwarding remote
    ForceCommand /sbin/nologin
    PermitTTY no
    PermitRootLogin no
    KbdInteractiveAuthentication no
    PasswordAuthentication no
    PubkeyAuthentication yes





monitor and restart ssh sessions

The original idea and the mechanism were from rstunnel (Reliable SSH Tunnel).


# Centos 7

yum install autossh

# Check Version

autossh -V

autossh 1.4e


autossh -M 0 -L 5000:localhost:3306


ssh -L 5000:localhost:3306


autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS]

-f       # causes autossh to drop to the background before running ssh.

         # The -f flag is stripped from arguments passed to ssh.

         # When -f is used, the "starting gate" time is set to 0.

         # 用 -f 必須 public/private key authentification


             Specifies how long ssh must be up before we consider it a successful connection. Default: 30 sec

-M port[:echo_port]

-M N

Specifies the base monitoring port to use.

Without the echo port, this port and the port immediately above it ( port + 1) should be something nothing else is using.

autossh will send test data on the base monitoring port, and receive it back on the port above. For example,

if you specify "-M 20000", autossh will set up forwards so that it can send data on port 20000 and receive it back on 20001.

-M 0

Setting the monitor port to 0 turns the monitoring function off, and autossh will only restart ssh upon ssh's exit.

For example, if you are using a recent version of OpenSSH,

you may wish to explore using the ServerAliveInterval and ServerAliveCountMax options

to have the SSH client exit if it finds itself no longer connected to the server.

In many ways this may be a better solution than the monitoring port.

ServerAliveInterval (Default: 0)

Sets a timeout interval in seconds after which if no data has been received from the server,

ssh will send a message through the encrypted channel to request a response from the server.

ServerAliveCountMax (Default: 3)

If this threshold is reached while server alive messages are being sent,

ssh will disconnect from the server, terminating the session.

# Default Values:

autossh -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3"

Server Side:

建立 user

useradd -m -s /bin/false autossh

建立 key

su -s /bin/bash autossh


mv ~/.ssh/ ~/.ssh/authorized_keys

cat ~/.ssh/id_rsa

Client Side:

# Basic

autossh -M 0 -R 2222:localhost:22 autossh@remotemachine

 * 最小切需要加 "-M 0"

# 測試

mkdir ~/ssh-key

chmod 700 ~/ssh-key

# 保存上個 step cat 出來的 key

vim ~/ssh-key/sshgw.key

chmod 400 /root/ssh-key/sshgw.key

autossh -N -M 0-R 2222:localhost:22 autossh@remotemachine -i /root/ssh-key/sshgw.key

-N      Do not execute a remote command. 沒有 -N 時, 那會獲得一個 shell

# 成功得在 server side 會見到

netstat -ntlp | grep ssh

tcp   0      0*    LISTEN   3092/sshd

# 斷線測試

killall -u autossh

log (/var/log/messages)

Jul 21 16:30:24 centos7 autossh[13647]: ssh exited with error status 255; restarting ssh
Jul 21 16:30:24 centos7 autossh[13647]: starting ssh (count 3)
Jul 21 16:30:24 centos7 autossh[13647]: ssh child pid is 13657



Description=AutoSSH tunnel service everythingcli MySQL on local port 5000

ExecStart=/usr/bin/autossh -M 0 -NL 5000:localhost:3306 autossh@myserver -p 1022


systemctl daemon-reload

systemctl start autossh-mysql-tunnel.service

systemctl enable autossh-mysql-tunnel.service




SSH connection daemon

sidedoor maintains an SSH connection or tunnel with a shell script daemon.

 - /bin/sh

 - while true; do

與 autossh 比較

sidedoor is a minimalistic shell script daemon.

autossh is a more extensive and configurable C program.





Host remotemachine
  User          autossh
  Port          22
  IdentityFile  ~/ssh-key/sshgw.key

  ServerAliveInterval 10
  ServerAliveCountMax 3

  # local 的 13306 相當於 remote 的 3306
  #LocalForward  13306 localhost:3306
  # remote 的 2222 相當於 local 的 22
  RemoteForward  2222 localhost:22


sshd 限制只可以 tunnel 去某 IP:Port



Match User some-user
   #AllowTcpForwarding yes
   #PermitTunnel no
   #GatewayPorts no
   X11Forwarding no
   AllowAgentForwarding no
   PermitOpen localhost:3306
   ForceCommand echo 'This account can only be used for mysql tunnel'


Limit local 'ssh -L' port forwarding (limit connect to the specified host and port)

Multiple forwards may be specified by separating them with whitespace

PermitOpen *:*            # Default
PermitOpen host:port
PermitOpen none

* 如果 User 有得 shell access, 那 PermitOpen 限制形同虛設, 因為 User 可以用 rinetd


AllowTcpForwarding yes(Default) | no | local | remote |

local: to allow local

remote:  to allow remote forwarding only