ssh命令¶
各参数含义:
-C 传输时压缩数据
-f 输入密码登陆后,ssh进入后台运行
-n 关闭标准输入
-N 不执行远程命令,只提供端口转发。仅用于ssh2协议
-g 允许远程主机连接ssh转发端口
-D 设置socks代理地址和监听端口,如果是只允许本地访问则指定IP为127.0.0.1
-l ssh登陆用户名
-i 指定ssh登陆用的私钥,如果是用公钥、私钥对登陆则需要指定
-q 安静模式
-o 指定options
-T Disable pseudo-terminal allocation.(禁止远程分配终端)
-t Force pseudo-terminal allocation.
-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket
选项¶
-vvvvv选项¶
打印5级debug日志:
ssh -vvvvv user@ip
-L选项(正向代理)¶
相当于 iptable 的 port forwarding
命令:
-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket
对应的config配置:
格式:
LocalForward 本地端口 远程主机:远程端口
示例:
LocalForward 5900 0:5900
用法1:把远程端口(C)映射到其他机器(B):
// HostB 上启动一个 PortB 端口,把 HostC:PortC 映射到 PortB 上
// 在 HostB 上运行:
$ ssh -L 0.0.0.0:PortB:HostC:PortC user@HostC
// 访问 HostB:PortB 相当于访问 HostC:PortC
// (和 iptable 的 port-forwarding 类似)
用法2:通过跳板(B)把远程端口(C)映射到本地端口(A):
// 说明
// HostA不能直接访问HostC,HostB可以访问HostC
// HostA 上启动一个 PortA 端口,通过 HostB 转发到 HostC:PortC上
// 在 HostA 上运行
$ ssh -L 0.0.0.0:PortA:HostC:PortC user@HostB
// 这时访问 HostA:PortA 相当于直接访问 HostC:PortC(使用HostB为中介)
示例: 把远端的端口3306影射到本地的3308(把远端的mysql通过本地访问):
$ ssh -L 3308:<ip>:3306 <user>@<host>
// 因为本机不能访问mysql,但host机能访问mysql
备注
两种用法的区别是,第一种用法本地到跳板机 HostB 的数据是明文的,而第二种用法一般本地就是 HostA, 访问本地的 PortA,数据被 ssh 加密传输给 HostB 又转发给 HostC:PortC。
用法3:把远程机器端口(C)映射到本地端口(A):
$ ssh -L PortA:localhost:PortC user@HostC
// 注意: 这儿的 localhost 其实是在HostC上的localhost
// 本质是用法2的变种: HostB 和 HostC 是同一机器的情况
-R选项(反向代理)¶
相当于 frp 或者 ngrok
命令:
-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
“反向代理”就是让远端启动端口,把远端端口数据转发到本地:
// HostA 将自己可以访问的 HostB:PortB 暴露给外网服务器 HostC:PortC,在 HostA 上运行
$ ssh -R HostC:PortC:HostB:PortB user@HostC
// 链接 HostC:PortC 就相当于链接 HostB:PortB
使用时需修改 HostC 的 /etc/ssh/sshd_config 添加:
GatewayPorts yes
备注
相当于内网穿透,比如 HostA 和 HostB 是同一个内网下的两台可以互相访问的机器,HostC是外网跳板机,HostC不能访问 HostA,但是 HostA 可以访问 HostC。那么通过在内网 HostA 上运行 ssh -R 告诉 HostC,创建 PortC 端口监听,把该端口所有数据转发给我(HostA),我会再转发给同一个内网下的 HostB:PortB。同内网下的 HostA/HostB 也可以是同一台机器,换句话说就是内网 HostA 把自己可以访问的端口暴露给了外网 HostC。
备注
相当于再 HostA 上启动了 frpc,而再 HostC 上启动了 frps。
-D选项(socket5代理)¶
相当于 ss/ssr
命令:
-D [bind_address:]port
指定一个动态应用级端口做转发,然后可以在浏览器做代理,通过指定服务器进行访问(如翻墙):
ssh -D 7070 username@yourserver.com
实例:
ssh -CfNg -D 0.0.0.0:1080 -l username xxx.xxx.xxx.xxx
-o选项(指定options)¶
命令:
-o option
常用options:
-oPort=6000: 指定连接时使用的端口号为 6000
-o 'ProxyCommand ...': 通过代理(proxy)连接到远程主机
ProxyCommand详解:
1. 通过 netcat 进行代理:
ssh -o 'ProxyCommand nc -X 5 -x proxy-server:1080 %h %p' user@remote-host
2. 通过 socat 进行代理:
ssh -o 'ProxyCommand socat - PROXY:proxy-server:%h:%p,proxyport=1080' user@remote-host
3. 通过 sshuttle 进行代理:
ssh -o 'ProxyCommand sshuttle -r user@proxy-server %h:%p' user@remote-host
4. 通过 corkscrew 进行代理:
ssh -o 'ProxyCommand corkscrew proxy-server 8080 %h %p' user@remote-host
SetEnv详解:
ssh -o "SetEnv Key=value" user@remote-host
-t选项¶
在 SSH 连接中分配一个伪终端(pseudo-terminal)
This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services.
Multiple -t options force tty allocation, even if ssh has no local tty.
通常用于在远程服务器上执行交互式命令或程序。
它会告诉 SSH 客户端在远程服务器上打开一个伪终端,以便用户可以与远程服务器进行交互,就像直接在本地终端中执行命令一样。
使用 -t 选项可以确保在 SSH 连接中正确处理输入和输出,使得用户可以正确地与远程服务器进行交互。
sshd命令¶
安装:
sudo apt install openssh-server
sshs命令¶
增强 SSH 管理和使用效率的工具,主要面向那些需要管理多个 SSH 连接的用户。与传统的 ssh 命令相比,sshs 提供了更便捷的方式来维护和快速连接多个 SSH 会话。
安装:
# 先确保系统上已安装 Node.js 和 npm/yarn npm install -g sshs or yarn global add sshs
torsocks¶
torsocks 专门用于通过 Tor(The Onion Router)网络 代理通信。Tor 网络是一种匿名通信网络,它通过多层加密和多跳路由让数据包通过一系列中间节点,以此来隐藏通信的来源和目标。
功能: torsocks 可以让用户将常规的命令(如 SSH 连接)通过 Tor 网络进行匿名化处理。使用 Tor 可以隐藏真实的 IP 地址,并加密流量,从而增强隐私性。
torsocks 是通过 Tor 网络来实现通信隐私,适合在希望隐藏身份或访问 .onion 隐匿服务时使用。
示例:
torsocks ssh -o "SetEnv SECRET=Dp..." root@smkxxxxx.onion
安装:
# Debian/Ubuntu
sudo apt-get install -y torsocks
# CentOS
sudo yum install torsocks # CentOS 或 Fedora 早期版本
# Arch Linux
sudo pacman -S torsocks
# mac
brew install torsocks
gsocket¶
gsocket 是一个用于 穿越防火墙 和 NAT(网络地址转换) 的工具,允许通过防火墙等限制网络环境建立对外的网络连接。
功能: gsocket 可以实现 P2P(点对点)通信,即使两个主机都位于受限的网络(如防火墙内)。它使用一种称为 UDP打洞(UDP hole punching)的技术,通过外部服务器进行连接协调,建立直接的通信通道。
gsocket 则是用于穿透网络限制,如防火墙和 NAT,确保可以在复杂网络条件下建立直接的 SSH 连接。
示例:
# 使用 gsocket 来建立 SSH 连接时,可以绕过网络限制,确保 SSH 能够正常进行,即便网络环境是封闭或受限的 gsocket -s OTVkOGENmFjM ssh -o "SetEnv SECRET=Dp..." root@8lgm.segfault.gsocket
安装:
# macOS
brew install gsocket
# 其他
git clone https://github.com/hackerschoice/gsocket.git
周边ssh命令¶
ssh-keygen命令¶
// 删除known_hosts中对应host/ip的记录
ssh-keygen -R <hostname>
ssh-keygen -R <ip_address>
// 显示key and ascii art representation
ssh-keygen -l -f <filePath>
ssh-keygen -lv -f ~/.ssh/known_hosts //以图形化的方式展示
// 生成pem格式的密钥
ssh-keygen -t rsa -m pem
// 生成到指定文件
ssh-keygen -t rsa -m pem -f <file>.pem
ssh-add命令相关¶
// ssh-add命令是把专用密钥添加到ssh-agent的高速缓存中
// 语法
ssh-add [-cDdLlXx] [-t life] [file ...]
ssh-add -s pkcs11
ssh-add -e pkcs11
选项:
-D: 删除ssh-agent中的所有密钥.
-d: 从ssh-agent中的删除密钥
-e: pkcs11:删除PKCS#11共享库pkcs1提供的钥匙。
-s: pkcs11:添加PKCS#11共享库pkcs1提供的钥匙。
-L: 显示ssh-agent中的公钥
-l: 显示ssh-agent中的密钥
-t: life:对加载的密钥设置超时时间,超时ssh-agent将自动卸载密钥
-X: 对ssh-agent进行解锁
-x: 对ssh-agent进行加锁
实例:
把专用密钥添加到 ssh-agent 的高速缓存中:
ssh-add ~/.ssh/id_dsa
2、从ssh-agent中删除密钥:
ssh-add -d ~/.ssh/id_xxx.pub
3、查看ssh-agent中的密钥:
ssh-add -l
mac专用 [1]:
-K: When adding identities, each passphrase will also be stored in the user's keychain.
When removing identities with -d, each passphrase will be removed from it.
$ ssh-add -K [path/to/your/ssh-key]
ssh-copy-id¶
ssh-copy-id 将本机的公钥复制到远程机器的authorized_keys文件中,ssh-copy-id也能让你有到远程机器的home, ~./ssh , 和 ~/.ssh/authorized_keys的权利
用ssh-copy-id将公钥复制到远程机器中:
$ ssh-copy-id -i .ssh/id_rsa.pub username@192.168.x.xxx
sshpass¶
安装:
# yum install sshpass
$ sudo apt-get install sshpass
Usage:
sshpass [-f|-d|-p|-e] [-hV] command parameters
-f filename Take password to use from file
-d number Use number as file descriptor for getting password
-p password Provide password as argument (security unwise)
-e Password is passed as env-var "SSHPASS"
With no parameters - password will be taken from stdin
示例:
$ export SSHPASS='my_pass_here'
$ sshpass -e ssh aaronkilik@10.42.0.1
如何使 SSH 会话保持活动状态¶
【参考】如何使 SSH 会话保持活动状态: https://linuxiac.com/how-to-keep-ssh-session-alive/
client配置 emacs ~/.ssh/config
Host *
ServerAliveInterval 120
ServerAliveCountMax 30
Host: The configurations specified only apply to the hosts listed following the “Host” keyword. Because we used a wildcard character (*), they apply to all hosts.
ServerAliveInterval: 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. The default is 0, indicating that these messages will not be sent to the server.
ServerAliveCountMax: Sets the number of server alive messages which may be sent without SSH receiving any messages back from the server. If this threshold is reached while server-alive messages are being sent, SSH will disconnect from the server, terminating the session. The default value is 3.
server配置 emacs /etc/ssh/sshd_config
TCPKeepAlive yes
ClientAliveInterval 120
ClientAliveCountMax 30
TCPKeepAlive: Specifies whether the system should send TCP keepalive messages to the client.
ClientAliveInterval: Sets a timeout interval in seconds, after which, if no data has been received from the client, the SSH server will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client.
ClientAliveCountMax: Sets the number of client alive messages which may be sent without the SSH server receiving any messages back from the client. If this threshold is reached while client-alive messages are being sent, the SSH server will disconnect the client, terminating the session. The default value is 3.
【问题解决】避免SSH连接因超时闲置断开:
用SSH过程连接电脑时,经常遇到长时间不操作而被服务器踢出的情况,常见的提示如:
Write failed: Broken pipe
这是因为如果有一段时间在SSH连接上无数据传输,连接就会断开。解决此问题有以下几种方法:
1. 修改 ``/etc/ssh/ssh_config`` 文件(可分在服务器端还是客户端)(需要root权限):
* 在客户端设置, 添加如下一行(此后该系统里的用户连接SSH时,每60秒会发一个KeepAlive请求,避免被踢):
ServerAliveInterval 60
* 在服务器端设置, 添加如下设置(应注意启用该功能后,安全性会有一定下降[比如忘记登出时……]):
ClientAliveInterval 60
* 注意,执行完上面修改后,需要重启sshd服务::
service sshd reload
2. 修改 ``~/.ssh/config`` 文件,在此文件中增加如下一句::
ServerAliveInterval 60
保存退出,重新开启用户的shell,则再ssh远程服务器的时候,不会因为长时间操作断开。应该是加入这句之后,ssh客户端会每隔一段时间自动与ssh服务器通信一次,所以长时间操作不会断开。
3. 修改 ``/etc/profile`` 配置文件,增加::
TMOUT=1800
这样30分钟没操作就自动LOGOUT
4. 利用expect 模拟键盘动作,在闲置时间之内模拟地给个键盘响应,将下列代码保存为xxx,然后用expect执行::
#!/usr/bin/expect
set timeout 60
spawn ssh user@host
interact {
timeout 300 {send "\x20"}
}
expect xxx
接着按提示输入密码就可以了,这样每隔300秒就会自动打一个空格(\x20),具体的时间间隔可以根据具体情况设置。
5. 如果你在windows下通过工具连接,可以设置为
secureCRT:选项---终端---反空闲 中设置每隔多少秒发送一个字符串,或者是NO-OP协议包
putty:putty -> Connection -> Seconds between keepalives ( 0 to turn off ), 默认为0, 改为300.
常见问题¶
* Agent admitted failure to sign using the key.
* Permission denied (publickey,gssapi-with-mic).
* Permission denied (publickey,keyboard-interactive).
* Permission denied (publickey,password). // 3次密码输入错误
* ssh_exchange_identification: read: Connection reset by peer(1.运营商2.尝试次数太多ip被防火墙干掉了)
常见问题 => Too many authentication failures:
>> ssh root@58.56.108.133
Received disconnect from 58.56.108.133: 2: Too many authentication failures for root
//原因: .ssh/文件夹下面的东西太多了
ssh中“Host key verification failed.“的解决方案:
这个问题的原理和比较长久的解决方案:
用OpenSSH的人都知ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts
当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告,避免你受到DNS Hijack之类的攻击
SSH对主机的public_key的检查等级是根据StrictHostKeyChecking变量来配置的
默认情况下,StrictHostKeyChecking=ask
简单所下它的三种配置值:
1.StrictHostKeyChecking=no
# 最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用
# 如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告
2.StrictHostKeyChecking=ask
# 默认的级别,就是出现刚才的提示了
如果连接和key不匹配,给出提示,并拒绝登录
3.StrictHostKeyChecking=yes #最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息
对于我来说,在内网的进行的一些测试,为了方便,选择最低的安全级别
在.ssh/config(或/etc/ssh/ssh_config)中配置:
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Unable to negotiate with xxxxx no matching host key type found. Their offer: ssh-rsa:
// 注: Mac发现的此问题
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
示例:
Host ssh.zhaoweiguo.com
HostName ssh.zhaoweiguo.com
User zwg
Port 22
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
原因:
8.8p1 版的 openssh 的 ssh 客户端默认禁用了 ssh-rsa 算法, 但是对方服务器只支持 ssh-rsa
# OpenSSH7.0 以后的版本不再支持 ssh-dss (DSA) 算法,官方的说法是这个算法太弱了
# MACOS 升到 10.12 附带的 openssh版本是 7.4
# 方法 1 终端命令添加 -oHostKeyAlgorithms=+ssh-rsa 如: ssh -oHostKeyAlgorithms=+ssh-rsa user@xxx
# 方法 2 追加以下内容
有了openssh密钥,如何生成putty ssh密钥:
假设openssh的私钥名为Identity则,在linux上,使用puttygen命令如下:
puttygen Identity -o Identity.ppk -O private
这样可以使用生成的.ppk文件登陆openssh服务器了
如何实现只能通过ssh私钥登录:
修改/etc/ssh/sshd_config文件:
PermitRootLogin no //修改为no(禁止root登陆)
PubkeyAuthentication yes //允许ssh登陆
AuthorizedKeysFile .ssh/authorized_keys //設定ssh登陆
PasswordAuthentication no //禁止密码登陆
//可以让你在远程机器上执行gui程序然后在"本地"显示图形
AllowTcpForwarding yes
X11Forwarding yes
ssh服务相关文件:
> cat /etc/ssh/sshd_config
AuthorizedKeysFile %h/.ssh/authorized_keys
PasswordAuthentication no: 指定不允许密码登录
PermitRootLogin no: 不允许root用户登陆
Port 22: 指定登录端口,默认TCP 22端口
AllowUsers happy test kaixin 指定允许登录用户
ChallengeResponseAuthentication yes: @todo 未知是做啥的(估计是用于expect脚本登录)
.ssh/config文件内容格式:
host eqitonghub
user git
hostname 60.216.116.245
port 22
identityfile ~/.ssh/gordon.git
mac使用跳板机时, 每次重启机器都要执行一次ssh-add命令输入密码 [1]:
原因:
ssh-add 这个命令不是用来永久性的记住你所使用的私钥的
实际上,它的作用只是把你指定的私钥添加到 ssh-agent 所管理的一个 session 当中
而 ssh-agent 是一个用于存储私钥的临时性的 session 服务
也就是说当你重启之后,ssh-agent 服务也就重置了。
解决:
Mac 系统内置了一个 Keychain 的服务及其管理程序,可以方便的帮你管理各种秘钥,其中包括 ssh 秘钥
ssh-add 默认将制定的秘钥添加在当前运行的 ssh-agent 服务中
但是你可以改变这个默认行为让它添加到 keychain 服务中,让 Mac 来帮你记住、管理并保障这些秘钥的安全性