SSH 隧道介绍:
SSH 隧道,也称为 SSH 端口转发,是一种利用 SSH 连接在两台机器之间创建安全加密通道的技术。可以通过一个安全的 SSH 连接来转发网络流量,从而绕过防火墙、访问受限网络资源或增强网络安全性。
SSH 隧道的工作原理:
SSH 隧道利用 SSH 连接的加密特性,将所有通过隧道的网络流量进行加密。 这使得即使在不安全的网络环境中,数据传输也保持安全。 SSH 客户端充当转发器,将本地流量转发到远程服务器,然后远程服务器再将流量转发到最终目的地。理解其工作原理和各种使用场景,可以更好地利用 SSH 隧道来提高网络安全性并访问受限资源。
SSH 隧道的类型:
SSH 隧道主要有三种类型:
本地端口转发 (Local Port Forwarding): 将本地机器上的一个端口转发到远程机器上的另一个端口。 这通常用于访问远程机器上运行的服务,而这些服务可能无法直接从本地机器访问(例如,由于防火墙限制)。
ssh -L <local_port>:<remote_host>:<remote_port> <user>@<ssh_server> :
将本地<local_port>
转发到远程主机<remote_host>
的<remote_port>
。远程端口转发 (Remote Port Forwarding): 将远程机器上的一个端口转发到本地机器上的另一个端口。 这通常用于让远程机器上的用户访问本地机器上的服务。
ssh -R <remote_port>:<local_host>:<local_port> <user>@<ssh_server> :
将远程主机<ssh_server>
的<remote_port>
转发到本地主机<local_host>
的<local_port>
动态端口转发 (Dynamic Port Forwarding): 创建一个 SOCKS 代理服务器,允许本地机器上的所有应用程序通过 SSH 连接访问网络。 这对于访问受限网络或匿名浏览非常有用。
ssh -D <local_port> <user>@<ssh_server> :
创建一个 SOCKS5 代理,监听本地<local_port>
创建SSH隧道命令示例:
ssh -qTfnND <local_port>:<remote_host>:<remote_port> <user>@<ssh_server_host>
<local_port>
: 本地机器上监听的端口号,本地应用程序将连接到此端口。<remote_host>
: 远程服务器的主机名或 IP 地址,你希望通过隧道访问的服务器。<remote_port>
: 远程服务器上监听的端口号。<user>
: 远程 SSH 服务器的用户名。<ssh_server_host>
: SSH 服务器的主机名或 IP 地址。
其中各个参数的含义如下:
ssh
: 调用 SSH 客户端程序。-q
: 静默模式,抑制大部分输出信息。-T
: 告诉 SSH 客户端不要分配伪终端。这对于仅用于隧道建立的连接非常重要,因为它防止了 SSH 客户端尝试执行交互式 shell。-f
: 后台运行模式。连接建立后,SSH 客户端会进入后台运行,不会阻塞当前终端。-N
: 不执行远程命令。这表示 SSH 连接只用于建立隧道,不会在远程主机上执行任何命令。-D
: 本地动态端口转发。这将创建一个 SOCKS5 代理,允许本地应用程序通过 SSH 隧道访问网络。
使用场景:
SSH 隧道在各种场景中都非常有用,包括:
访问受限网络资源: 如果本地机器无法直接访问远程服务器上的某个服务(例如,由于防火墙限制),可以使用本地端口转发创建一个 SSH 隧道,从而访问该服务。 这在访问公司内部网络、云服务器上的私有服务或其他受限网络资源时非常有用。
安全地访问公共 Wi-Fi: 在公共 Wi-Fi 网络上,网络流量可能容易被窃听。 使用 SSH 隧道可以加密网络流量,保护数据安全。
绕过地理限制: 某些网站或服务可能在某些地区被屏蔽。 使用 SSH 隧道可以通过一个位于不受限制地区的服务器访问这些资源。
访问数据库: 如果数据库服务器位于防火墙后面,可以使用 SSH 隧道安全地访问数据库,而无需在防火墙上打开数据库端口。
安全远程桌面访问: 可以使用 SSH 隧道来安全地访问远程桌面,即使远程桌面服务器的端口被防火墙阻止。
开发和测试: 在开发和测试过程中,可能需要访问本地机器上的服务,而这些服务可能无法直接从远程机器访问。 SSH 隧道可以帮助解决这个问题。
使用示例:
工作中,由于网络或安全限制等原因需要使用一台代理转发机器开个口子访问内网服务,使用SSH隧道动态端口转发是常用解决方案。
命令如下:
ssh -qTfnND 1234 remoteuser@remotehost
这个命令会在本地机器上创建一个 SOCKS5 代理,监听 1234 端口,我们可以使用本地浏览器作为访问客户端(推荐安装 Proxy SwitchyOmega 代理插件),配置 127.0.0.1:1234 代理将访问转发到远程入口机器,然后访问到内网服务,可以在本地和远程代理机器 /etc/hosts 文件中绑定要访问的域名解析地址。如果使用 SOCKS5 代理协议浏览器访问白屏,可以换成 SOCKS4 协议试试。
还有种常用的方式就是直接将远程入口机器做成代理转发服务器,或者使用云厂商SLB作为入口转发,使用LB这种配置域名转发,防火墙安全访问都会更安全方便,然后在本地浏览器将代理地址配置成 远程入口机器地址加端口 或 SLB地址加端口 就行。
SSH Config配置:
如果经常需要使用端口转发,可以将其写入到 ~/.ssh/config 配置文件中,省去在命令中添加选项和参数,示例如下:
Host ops # 别名 HostName 10.123.234.1 # SSH服务器IP User anzhihe # SSH服务器用户名 IdentityFile ~/.ssh/id_rsa_xxx # 私钥文件 Port 22 # SSH服务器端口 LocalForward 8443 127.0.0.1:443 # 本地端口转发(将本地8443端口的所有请求转发到远程主机的443端口) RemoteForward 80 127.0.0.1:80 # 远程端口转发(将远程主机的80端口的所有请求转发到本地主机的80端口) DynamicForward 127.0.0.1:1080 # 动态端口转发(将本地主机的1080端口作为socks5代理) ProxyCommand nc -X 5 -x IP:1080 %h %p # 将SSH服务器的请求转发到IP:1080端口 ServerAliveInterval 120 # 每120秒向SSH Server发送心跳包,默认累积三次超时即认为失去连接(在客户端设置) ClientAliveInterval 120 # 每120秒向客户端发送心跳包,确保在客户端不响应时关闭连接(在SSH服务端设置) ExitOnForwardFailure=yes StrictHostKeyChecking=no Compression=yes ForwardAgent=yes Host * User root KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 PubkeyAcceptedAlgorithms +ssh-rsa HostKeyAlgorithms +ssh-rsa ServerAliveInterval 30 ControlMaster auto ControlPath /tmp/ssh-%r@%h:%p ControlPersist yes StrictHostKeyChecking=no Compression=yes ForwardAgent=yes
### default for all ## ## Set override as per host ## Host server1 HostName server1.cyberciti.biz User nixcraft Port 4242 IdentityFile /nfs/shared/users/nixcraft/keys/server1/id_rsa ## Home nas server ## Host nas01 HostName 192.168.1.100 User root IdentityFile ~/.ssh/nas01.key ## Login AWS Cloud ## Host aws.apache HostName 1.2.3.4 User wwwdata IdentityFile ~/.ssh/aws.apache.key ## Login to internal lan server at 192.168.0.251 via our public uk office ssh based gateway using ## ## $ ssh uk.gw.lan ## Host uk.gw.lan uk.lan HostName 192.168.0.251 User nixcraft ProxyCommand ssh nixcraft@gateway.uk.cyberciti.biz nc %h %p 2> /dev/null ## Our Us Proxy Server ## ## Forward all local port 3128 traffic to port 3128 on the remote vps1.cyberciti.biz server ## ## $ ssh -f -N proxyus ## Host proxyus HostName vps1.cyberciti.biz User breakfree IdentityFile ~/.ssh/vps1.cyberciti.biz.key LocalForward 3128 127.0.0.1:3128 ## Now set defaults for all if not matched by any hosts ## Host * ForwardAgent no ForwardX11 no ForwardX11Trusted yes User nixcraft Port 22 Protocol 2 ServerAliveInterval 60 ServerAliveCountMax 30 ## Reuse an existing TCP connection for multiple concurrent SSH sessions. Host server1 HostName server1.cyberciti.biz ControlPath ~/.ssh/controlmasters/%r@%h:%p ControlMaster auto ## Through one host to reach another server i.e. jump host using ProxyCommand Host internal HostName 192.168.1.100 User vivek ProxyCommand ssh vivek@vpn.nixcraft.net.in -W %h:%p ControlPath ~/.ssh/controlmasters/%r@%h:%p ControlMaster auto ## Overriding ssh config file option Host ln.openvpn-sg-vpn1 ln.wireguard-sg-vpn1 Hostname 172.16.0.1 User vivek port 22 IdentityFile ~/.ssh/id_ed25519.pub StrictHostKeyChecking no ## create a new bash shell alias as follow ## ## create the alias use the following syntax in your ~/.bashrc file alias server1="ssh -i /nfs/shared/users/nixcraft/keys/server1/id_rsa -p 4242 nixcraft@server1.cyberciti.biz"
创建SSH端口转发用户:
建议为端口转发建立专门的账户,使用随机密码(当然使用私钥登录更好),并且禁掉其执行命令的权限。
# add user tunnel-user for ssh port forwarding sudo useradd -m tunnel-user # generate 10 random passwords with 16 length pwgen -sy1 16 10 # pick one password and set it to tunnel-user sudo passwd tunnel-user # disable shell for tunnel-user sudo chsh -s /bin/false tunnel-user
注意事项:
SSH 密钥认证: 始终优先使用 SSH 密钥认证而不是密码认证,以提高安全性。
防火墙配置: 确保你的本地和远程防火墙允许 SSH 连接和端口转发。
端口选择: 选择一个不太常用的本地端口号,以减少安全风险。
服务器信任: 确保能信任使用的 SSH 服务器,始终优先考虑安全性,并采取适当的措施来保护数据。
记住将示例中的占位符替换为实际的服务器地址、端口号和用户名。 选择一个未被使用的本地端口号。可以使用 ps aux | grep ssh
命令来检查 SSH 进程是否在后台运行。 要终止隧道,可以找到 SSH 转发进程的 PID 并使用 kill <PID>
命令终止它。
参考: