-L 本地端口转发

-R 远程端口转发

-D 动态端口转发

Example

# 本地端口转发
# 本地监听端口 9848,用户访问本机的 9848端口,最终访问 HostC的9848端口,通过HostB中转
ssh -L 9848:HostC:9848 user@HostB -N

# 远程端口转发
# 远程主机HostB监听端口 9848
# 用户访问HostB的 9848端口,最终访问 HostA 的9848端口,通过HostA中转
ssh -R 9848:localhost:9848 user@HostB -N

# 动态端口转发
# 本地监听1080端口 SOCKS5协议
# 用户配置本机的1080作为代理,http请求,会通过代理端口转到HostB,然后通过HostB访问http请求
ssh -D 1080 user@HostB -N

选项

-L 本地端口转发

-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket
    指定将本地(客户端)主机上给定 TCP 端口或 Unix 套接字的连接转发到远程端给定的主机和端口或
    Unix 套接字。具体做法是分配一个套接字,监听本地端的 TCP 端口(可选择绑定到指定的 
    bind_address 上)或 Unix 套接字。每当连接到本地端口或套接字时,连接就会通过安全通道转发,
    并连接到主机端口 hostport 或远程机器的 Unix 套接字 remote_socket。
    
    端口转发也可以在配置文件中指定。 只有超级用户才能转发特权端口。 可以用方括号指定 IPv6 地址。
    
    默认情况下,本地端口根据 GatewayPorts 设置绑定。 不过,也可以使用明确的 bind_address 
    将连接绑定到特定地址。bind_address 为 “localhost ”表示监听端口只绑定到本地使用,而空地址或
    “*” 则表示端口可从所有接口使用。

-R 远程端口转发

-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket
-R [bind_address:]port
    指定将远程(服务器)主机上给定 TCP 端口或 Unix 套接字的连接转发到本地。
    
    具体做法是分配一个套接字监听远程端的 TCP 端口或 Unix 套接字。每当连接到该端口或 Unix 套接
    字时,连接就会通过安全通道转发,并从本地机器连接到主机端口 hostport 或 local_socket 指定
    的明确目的地,如果没有指定明确的目的地,ssh 就会充当 SOCKS 4/5 代理,
    将连接转发到远程 SOCKS 客户端请求的目的地。
    
    端口转发也可以在配置文件中指定。只有以远程计算机 root 用户身份登录时,才能转发特权端口。
    可以用方括号指定 IPv6 地址。
    
    默认情况下,服务器上的 TCP 侦听套接字只绑定到环回接口。可以通过指定一个 bind_address 来重写。
    空的 bind_address 或地址 “*”表示远程套接字应监听所有接口。只有启用了服务器的 GatewayPorts
    选项(参见 sshd_config(5)),指定远程 bind_address 才会成功。
    
    如果端口参数为 “0”,监听端口将在服务器上动态分配,并在运行时报告给客户端。
    与 -O forward 一起使用时,分配的端口将被打印到标准输出中。

-D 动态端口转发

-D [bind_address:]port
    指定本地 “dynamic 动态 ”应用级端口转发。
    具体做法是在本地端分配一个监听端口的套接字,可选择绑定到指定的 bind_address 上。
    每当连接到该端口时,连接都会通过安全通道转发,然后使用应用程序协议确定从远程机器连接到哪里。
    目前支持 SOCKS4 和 SOCKS5 协议,ssh 将充当 SOCKS 服务器。
    只有 root 可以转发特权端口。 动态端口转发也可以在配置文件中指定。
    
    可以用方括号指定 IPv6 地址。 只有超级用户才能转发特权端口。 
    默认情况下,本地端口根据 GatewayPorts 设置绑定。
    不过,也可以使用明确的 bind_address 将连接绑定到特定地址。
    bind_address为 “localhost ”表示监听端口只绑定到本地使用,而空地址或 “*”表示端口应可从
    所有接口使用。

示例

本地端口转发

# HostA执行,HostA本地监听9848端口,通过HostB访问到HostC的9848
# 用户访问 -> HostA 9848 -> HostB 22 -> HostC 9848

# 监听 127.0.0.1 ,仅主机HostA可访问
ssh -L 9848:HostC:9848 user@HostB -N
ssh -L localhost:9848:HostC:9848 user@HostB -N

# 监听所有接口
ssh -L *:9848:HostC:9848 user@HostB -N
ssh -L :9848:HostC:9848 user@HostB -N

远程端口转发

# HostA执行,操控 HostB 主机监听 9848 端口
# 用户访问HostB的9848,实际是通过HostA访问 HostC的 9848 端口
# 用户访问 -> HostB 9848 -> HostA -> HostC 9848

# HostB 监听 127.0.0.1 仅本机访问
ssh -R 9848:HostC:9848 user@HostB -N
ssh -R localhost:9848:HostC:9848 user@HostB -N

# HostB监听 0.0.0.0,供所有地址访问
ssh -R :9848:HostC:9848 user@HostB -N
ssh -R *:9848:HostC:9848 user@HostB -N
# 注意:只有配置了 GatewayPorts yes,才可以监听 0.0.0.0 供所有访问,否则也只能仅主机访问


# 也可以转发本机的
# 用户访问 -> HostB 的 8888 端口 -> HostA -> HostA 的localhost:22 
ssh -R *:8888:localhost:22 user@HostB -N

动态端口转发

# HostA监听 1080 动态端口转发 SOCK5 协议
# 用户配置代理为 HostA的1080 SOCKS5
# 用户发起http请求 -> 代理 HostA 1080 -> 通过SSH协议到主机HostB -> HostB访问用户请求的HTTP地址
# 仅本机访问
ssh -D 1080 user@HostB -N

# 允许其它主机访问 HostA 的 1080 代理端口
ssh -D :1080 user@HostB -N
ssh -D *:1080 user@HostB -N

持久化

如何保持连接稳定和持久化?

1.通过autossh

安装

sudo apt -y install autossh

示例

# crontab 重启后执行,等待300s,运行autossh命令
# -fNR
# -f[SSH_OPTIONS] -f后面指定的是SSH的选项,N表示不执行远程命令,这对于转发端口很有用,R表示远程端口转发
# 16900:127.0.0.1:22
# 主机 HostB 监听 16900 端口,转发到本机的 22 端口,用户访问主机HostB的16900就是访问运行该命令本机的22端口

@reboot sleep 300 && autossh -fNR 16900:127.0.0.1:22 user@HostB

2.通过systemd

如果你希望 在开机时自动启动 SSH 隧道,可以使用 systemd

步骤 1:创建 systemd 服务

主机 A 上创建 /etc/systemd/system/ssh-tunnel.service

[Unit]
Description=SSH Tunnel to B
After=network.target

[Service]
ExecStart=/usr/bin/ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -R 9848:localhost:9848 user@B -N
Restart=always
User=root

[Install]
WantedBy=multi-user.target

步骤 2:启动并启用服务

systemctl daemon-reload
systemctl enable ssh-tunnel
systemctl start ssh-tunnel

标签: Linux, OpenSSH

添加新评论