ssh原理探析
SSH是什么?
SSH是一种网络协议,用于计算机之间的加密登录。登录信息全部加密,即使被中途截获,密码也不会泄露。
SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。常用的OpenSSH是自由软件。例如win10默认已经安装了OpenSSH 在 C:\Windows\System32\OpenSSH\ssh.exe
OpenSSH有两个可执行文件, ssh 与 sshd
知识与概念
https://juejin.cn/post/7028374997269757960
基本用法
ssh -p 22 user@host
安全性
初次登录时,会提示:
The authenticity of host 'host (12.18.429.21)' can't be established.
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)?
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:AOnp3rCzs8rUQCddTHOkicEoW8gq0s3gNcyE7eKhEAk.
ECDSA key fingerprint is MD5:c2:ac:7a:20:60:01:a5:55:00:ad:a0:d3:2c:6a:7a:1b.
无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?
用户无法知道远程主机的公钥指纹应该是多少,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。
别的网站也贴出公钥指纹冒充怎么办呢?没关系,客户端用此公钥加密的内容,别的网站不像正宗网站一样有对应的私钥来解开
当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。
公钥登录
所谓"公钥登录",原理很简单, 就是用户A将自己的公钥PubKey储存在远程主机B上。登录的时候,B会向A发送一段随机字符串,A用自己的私钥加密后,再发回来给B。B用事先储存的公钥进行解密(比对解密结果与下发的字符串),如果成功,就证明A有PubKey对应的私钥,是可信的,直接免密登录shell。
ssh-keygen #生成密钥对
ssh-copy-id user@host #传公钥给服务器,从此可免密
如果还是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,确定以下配置。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。(ssh-copy-id user@host其实就是这么做的。)
如果还是需要密码,可以查看一下日志, 日志路径因系统而异(见本文),我遇到过的一个问题是 ~/.ssh/authorized_keys读写权限不对, SSH不希望home与home/.ssh对组有写权限, 因此chmod 755就解决了。
sshd工作原理与涉及的系统调用
- 读取sshd_config, listen
- ConnFD = accept ; fork + waitpid 每个连接处理
- ssh协议,握手,交换密钥
- 账号密码验证: (这个是sshd要求的,不是操作系统要求,你自己写sshd的可以设计不要)
- PAM(可插拔):
- pam_unix.so 读/etc/shadow,对比
- 或者 PublicKey 对比 ~/.ssh/authorized_key
- 非PAM: getpwnam 与 crypt 来验证
- PAM(可插拔):
- 设置sid, 分配pty
- fork, 设父进程为"M", 子进程为"S"
- S执行: setuid + setgid 创建会话, 切换用户
- S执行: forkpty + openpty(master, slave) + tcsetattr + ioctl
- S执行:
dup2(slave, STD*);
- 启动shell
- S执行:
exec("/bin/bash")实际执行的是pw->shell - 自此 S 由shell接管, 此后对pty slave的读写都是shell及子进程导致的。
- S执行:
- "M"执行
- read(pty), 编码加密send(ConnFD)
- recv(ConnFD), 解密后 write(pty)
可以做一个小实验,有ssh时ps 一下获取一下自己的bash的tty
$ ps
PID TTY TIME CMD
3855325 pts/12 00:00:00 bash
3861176 pts/12 00:00:00 ps
在另一个ssh里,执行echo, 并观察之前ssh的输出
$ sudo echo "OK" > /dev/pts/12
ssh工作原理
- connect()
- ssh协议,握手
- 读console,加密send
- recv, 解密写console
只管文件形式读写console, console可能是serial,也可能是xterm,也可能是windows黑窗口,具体console怎么渲染怎么输入,不归ssh管。
sshd配置
作为服务器,sshd的配置也很重要。
sshd的配置在 /etc/ssh/sshd_config 其主要的配置项是:
ssh的配置也在此目录,叫/etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding yes
Ciphers aes128-ctr,aes192-ctr,aes256-ctr
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256
key文件应该是安装时生成的。这些key对应的公钥是 ssh_host_ecdsa_key.pub等,用Base64编码过了。之后Base64解码后的二进制公钥会随sshv2发送给客户端,在抓到的包里是的Server:Elliptic Curve Diffie-Hellman Key Exchang包的ECDSA public key字段。
X11-forwarding 原理与排错
sshd读取/etc/ssh/sshd_config X11Forwarding yes 之后
- 本地监听一个 6010 端口
sshd-sess 726791 pxf_god 10u IPv4 1956367 0t0 TCP *:6010 (LISTEN)
- XClient程序比如xclock会读取
$DISPLAY环境变量 (不管是ssh还是本地都读这个) - XClient并不知道会不会被 forwarding, 他只认为
$DISPLAY指定的就是XServer - XClient向6010发指令
- sshd-sess 向 sshd 转发
- sshd 通过加密连接向 MobaXterm ssh转发
- MobaXterm ssh向X Server转发
- X Server绘制
$DISPLAY 变量是由谁设置的?
$DISPLAY 是由 SSH 服务器端(sshd)设置的,但它的值是由 SSH 客户端(ssh) 提供的。
- SSH 客户端 在连接时(使用 -X 或 -Y)会告诉服务器:
- "我要启用 X11 Forwarding,请分配一个 DISPLAY 给我"。
- SSH 服务器 收到请求后:
- 检查 sshd_config 是否允许 X11 Forwarding(X11Forwarding yes)。
- 分配一个可用的 DISPLAY 编号(通常是 :10.0,对应端口 6010)。
- 在用户的 shell 环境中设置 DISPLAY=localhost:10.0。
没有监听6010, 也没有DISPLAY变量
通常是xauth没安装
sudo pacman -S xorg-xauth # Arch
sudo apt install xauth # Debian
转发的本质:X11 协议通信
ssh完全不知道里面的内容,只是转发,只有xclient与xserver需要理解其中内容。
转发的内容是 X11 协议的数据包,主要包括:
- 绘制指令(如画线、填充矩形、渲染文本等)。
- 事件通知(如键盘输入、鼠标点击、窗口焦点变化)。
- 资源管理(如图片、字体、颜色等对象的引用和操作)。
- 不是直接转发像素: 像素数据体积庞大, 服务器可以硬件加速渲染
同一条tcp连接上的逻辑通道
SSH 协议在一条 TCP 连接上创建了多个 逻辑通道(channels),每个通道用于传输不同类型的数据。这些通道是独立的,SSH 协议通过 通道 ID 来区分它们。
- 当你在 SSH 会话中运行命令时,命令的标准输入(stdin)、标准输出(stdout)和标准错误(stderr)都会通过默认的通道传输。例如:
- X11 程序的所有图形数据都会通过 X11 通道传输到 SSH 客户端。
- 通道 ID 位于 SSH 协议数据包的 有效载荷 部分。
- 当 SSH 协议需要传输某种类型的数据时,它会将数据封装为一个 通道数据包。
- 通道数据包的有效载荷中会包含 通道 ID,用于标识该数据包属于哪个逻辑通道。
- 端口转发(forwarding ports) 也是channel的另一用途
SSH 协议中连接(connection) 通过 逻辑通道(channels) 区分不同类型数据的机制,本质上就是一种 多路复用(Multiplexing) 技术
本地端口转发(Local forwarding)
ssh -D 8080 user@host 客户端ssh.exe启动时,监视本地的端口bind(:8080)+listen,收到的包将转发给host。
假定host1是本地主机,host2是远程主机。由于种种原因,这两台主机之间无法直接连通。但是,另外还有一台host3,可以同时连通前面两台主机。因此,通过host3跳板,将host1连上host2。
# host1
ssh -L 2121:host2:21 host3
L参数一共接受三个值,分别是"本地端口:目标主机:目标端口"。指定SSH绑定本地端口2121,然后指定host3将所有的数据,转发到目标主机host2的21端口(假定host2运行FTP,默认端口为21)。
# host1, 开ftp连本地的2121,被转发给host3
ftp localhost:2121
# host3 转给host2
ssh -L 5900:localhost:5900 host3
远程端口转发(Remote forwarding)
"远程端口转发"的前提条件是,host1和host3两台主机都有sshd和ssh。
ssh -R 2121:host2:21 host1
R参数也是接受三个值,分别是"远程主机端口:目标主机:目标主机端口"。让host1监听它自己的2121端口,然后将所有数据经由host3,转发到host2的21端口。由于对于host3来说,host1是远程主机,所以这种情况就被称为"远程端口绑定"。
vscode的基本功能ssh到远程,打开远程文件操作,就像windows本地操作一样,应该就是远程的node进程借助ssh转发功能与本地的vscode通信来办到的
其他参数
-N-TN参数,表示只连接远程主机,不打开远程shell;T参数,表示不为这个连接分配TTY。一起用,代表这个SSH连接只用来传数据,不执行远程操作。-ff参数,表示SSH连接成功后,转入后台运行。这样一来,你就可以在不中断SSH连接的情况下,在本地shell中执行其他操作。
HTTPS
HTTPS这个协议与SSH有异曲同工之处! HTTPS概念:HTTPS是身披SSL外壳的HTTP(超文本传输协议)。
ssh协议
用wireshark抓包,过滤条件是BPF tcp port 22,即仅关心ssh通信。

- 先是TCP握手
- 由服务器告诉客户端 ssh版本。这个是文本可读的,
SSH-2.0-OpenSSH_7.4再以\r\n结尾 - 客户端告诉服务器自己的版本
- 客户端提交客户端的公钥算法。 图中的Key Exchange Init
- 服务器下发服务器的公钥算法。两端啰嗦一番,交代底细,支持哪些算法, 都是文本信息,人工可读的明文。

- 客户端上传公钥
- 服务器下发公钥
- 之后的信息就都是用对方的公钥加密过的了,因为只有对面才有钥匙才能解开,所以是安全的。

- 可以看到后面抓到的包都显示“Encrypted Packet”
每个“Encrypted Packet”都包括一个4字节的长度信息L与一个L字节长度的载荷,载荷的内容是对面公钥加密过的,本例的算法是 “curve25519-sha256”
那么,我把抓到的包保存下来发布到网络上有什么问题吗?不会,都是公钥和里面的加密内容,无妨。
ssh与sshd之间通信协议是什么
[pxfgod@VM-12-10-centos ~]$ ps
PID TTY TIME CMD
16180 pts/7 00:00:01 bash
19951 pts/7 00:00:00 ps
pts/7是 ssh会话建立之后, sshd虚拟的一个tty。sshd会分配一个tty并运行bash。
如果有两个连接,一个分配了 pts/7 一个分配了 pts/8, 在pts/7上执行sudo echo vvv > /dev/pts/8 可以看到另一个session里打印了vvv
通过ps -ef可以看到父进程, 推测ssh与sshd握手之后, sshd fork了,然后子进程启动了bash。sshd是一个 accept+fork的服务模型。
[pxfgod@VM-12-10-centos ~]$ ps -ef | grep 16180
pxfgod 16180 16134 0 14:50 pts/7 00:00:01 -bash
pxfgod 21285 16180 0 15:11 pts/7 00:00:00 ps -ef
pxfgod 21286 16180 0 15:11 pts/7 00:00:00 grep --color=auto 16180
[pxfgod@VM-12-10-centos ~]$ ps -ef | grep 16134
pxfgod 16134 16122 0 14:50 ? 00:00:00 sshd: pxfgod@pts/7
pxfgod 16180 16134 0 14:50 pts/7 00:00:01 -bash
pxfgod 21415 16180 0 15:11 pts/7 00:00:00 grep --color=auto 16134
[pxfgod@VM-12-10-centos ~]$ ps -ef | grep 16122
root 16122 1091 0 14:50 ? 00:00:00 sshd: pxfgod [priv]
pxfgod 16134 16122 0 14:50 ? 00:00:00 sshd: pxfgod@pts/7
pxfgod 21535 16180 0 15:12 pts/7 00:00:00 grep --color=auto 16122
或者可以用pstree直接找到父子关系
[pxfgod@VM-12-10-centos ~]$ sudo readlink /proc/16180/exe
/usr/bin/bash
[pxfgod@VM-12-10-centos ~]$ sudo readlink /proc/16134/exe
/usr/sbin/sshd
[pxfgod@VM-12-10-centos ~]$ sudo readlink /proc/16122/exe
/usr/sbin/sshd
[pxfgod@VM-12-10-centos ~]$ sudo ls -l /proc/16180/fd
total 0
lrwx------ 1 pxfgod root 64 Jul 18 14:50 0 -> /dev/pts/7
lrwx------ 1 pxfgod root 64 Jul 18 14:50 1 -> /dev/pts/7
lrwx------ 1 pxfgod root 64 Jul 18 14:50 2 -> /dev/pts/7
lrwx------ 1 pxfgod root 64 Jul 18 15:01 255 -> /dev/pts/7
[pxfgod@VM-12-10-centos ~]$ sudo ls -l /proc/16134/fd
total 0
lrwx------ 1 root root 64 Jul 18 15:15 0 -> /dev/null
lrwx------ 1 root root 64 Jul 18 15:15 1 -> /dev/null
lrwx------ 1 root root 64 Jul 18 15:15 13 -> /dev/ptmx
lrwx------ 1 root root 64 Jul 18 15:15 14 -> /dev/ptmx
lrwx------ 1 root root 64 Jul 18 15:15 2 -> /dev/null
lrwx------ 1 root root 64 Jul 18 15:15 3 -> socket:[531037334]
lrwx------ 1 root root 64 Jul 18 15:15 4 -> socket:[531036878]
lrwx------ 1 root root 64 Jul 18 15:15 5 -> socket:[531037404]
l-wx------ 1 root root 64 Jul 18 15:15 6 -> /run/systemd/sessions/611572.ref
lr-x------ 1 root root 64 Jul 18 15:15 7 -> pipe:[531036917]
l-wx------ 1 root root 64 Jul 18 15:15 8 -> pipe:[531036917]
lrwx------ 1 root root 64 Jul 18 15:15 9 -> /dev/ptmx
[pxfgod@VM-12-10-centos ~]$ sudo ls -l /proc/16122/fd
total 0
lr-x------ 1 root root 64 Jul 18 14:50 0 -> /dev/null
lrwx------ 1 root root 64 Jul 18 14:50 1 -> /dev/null
lrwx------ 1 root root 64 Jul 18 14:50 2 -> /dev/null
lrwx------ 1 root root 64 Jul 18 14:50 3 -> socket:[531037334]
lrwx------ 1 root root 64 Jul 18 14:50 4 -> socket:[531036878]
lrwx------ 1 root root 64 Jul 18 14:50 5 -> /dev/ptmx
l-wx------ 1 root root 64 Jul 18 15:16 6 -> /run/systemd/sessions/611572.ref
lrwx------ 1 root root 64 Jul 18 15:16 7 -> socket:[531037405]
OpenSSH 研究
编译&安装 OpenSSH
sudo apt update
sudo apt install build-essential zlib1g-dev libssl-dev
sudo apt install autoconf
git clone ...
autoreconf
./configure CFLAGS="-ggdb -O0" CXXFLAGS="-ggdb -O0" LDFLAGS="-ggdb3"
make -j4
pacman -S zlib openssl #安装依赖库
如果是archlinux,安装,然后其他一样。
./configure --prefix=/usr/ \
--sysconfdir=/etc/ssh/ \
--with-ssl-dir=/usr/local/ssl \
--with-md5-passwords \
--mandir=/usr/share/man/
安装还需要设置sshd用户编辑服务配置文件
[/etc/group]
sshd:x:74:
[/etc/passwd]
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
vim /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
#After=network.target sshd-keygen.service
#Wants=sshd-keygen.service
After=network.target
[Service]
#Type=notify
#EnvironmentFile=/etc/sysconfig/sshd
#ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecStart=/usr/sbin/sshd
#ExecReload=/bin/kill -HUP $MAINPID
#KillMode=process
#Restart=on-failure
#RestartSec=42s
[Install]
WantedBy=multi-user.target
systemctl enable sshd
systemctl restart sshd
https://juejin.cn/post/7062370067903676453
协议
读网络协议
#0 __GI___libc_read (fd=3, buf=0x7f03fed2f010, nbytes=262144) at ../sysdeps/unix/sysv/linux/read.c:25
#1 0x000055de85e2baf2 in sshbuf_read (fd=3, buf=0x55de8780ec80, maxlen=262144, rlen=0x7fffdd37bfa8) at sshbuf-misc.c:286
#2 0x000055de85e54b95 in ssh_packet_process_read (ssh=0x55de8780d280, fd=3) at packet.c:1795
#3 0x000055de85df3dc3 in client_process_net_input (ssh=0x55de8780d280) at clientloop.c:642
#4 0x000055de85df6810 in client_loop (ssh=0x55de8780d280, have_pty=1, escape_char_arg=126, ssh2_chan_id=0)
b read if $rdi=4 读stdin
#0 0x000055de85e383f8 in channel_handle_rfd (ssh=0x55de8780d280, c=0x55de878236b0) at channels.c:1974
#1 0x000055de85e397f0 in channel_post_open (ssh=0x55de8780d280, c=0x55de878236b0) at channels.c:2202
#2 0x000055de85e3aa4a in channel_handler (ssh=0x55de8780d280, table=1, unpause_secs=0x0) at channels.c:2442
#3 0x000055de85e3bc7c in channel_after_poll (ssh=0x55de8780d280, pfd=0x55de8781ff70, npfd=3) at channels.c:2751
#4 0x000055de85df67fd in client_loop (ssh=0x55de8780d280, have_pty=1, escape_char_arg=126, ssh2_chan_id=0)
b write if $rdi==5 回显到ssh
#0 __GI___libc_write (fd=5, buf=0x55de87823820, nbytes=92) at ../sysdeps/unix/sysv/linux/write.c:25
#1 0x000055de85e38b03 in channel_handle_wfd (ssh=0x55de8780d280, c=0x55de878236b0) at channels.c:2060
#2 0x000055de85e39803 in channel_post_open (ssh=0x55de8780d280, c=0x55de878236b0) at channels.c:2203
#3 0x000055de85e3aa4a in channel_handler (ssh=0x55de8780d280, table=1, unpause_secs=0x0) at channels.c:2442
#4 0x000055de85e3bc7c in channel_after_poll (ssh=0x55de8780d280, pfd=0x55de8781ff70, npfd=4) at channels.c:2751
#5 0x000055de85df67fd in client_loop (ssh=0x55de8780d280, have_pty=1, escape_char_arg=126, ssh2_chan_id=0)
#0 ssh_packet_read_poll2 (ssh=0x557e70edf280, typep=0x7ffc65d825cf "", seqnr_p=0x7ffc65d825d0) at packet.c:1498
#1 0x0000557e6f0e46cf in ssh_packet_read_poll_seqnr (ssh=0x557e70edf280, typep=0x7ffc65d825cf "", seqnr_p=0x7ffc65d825d0)
at packet.c:1716
#2 0x0000557e6f0f02ea in ssh_dispatch_run (ssh=0x557e70edf280, mode=1, done=0x557e6f18a760 <quit_pending>) at dispatch.c:100
#3 0x0000557e6f0f0505 in ssh_dispatch_run_fatal (ssh=0x557e70edf280, mode=1, done=0x557e6f18a760 <quit_pending>)
at dispatch.c:133
#4 0x0000557e6f085ca4 in client_process_buffered_input_packets (ssh=0x557e70edf280) at clientloop.c:1166
#5 0x0000557e6f08663a in client_loop (ssh=0x557e70edf280, have_pty=1, escape_char_arg=126, ssh2_chan_id=0)
at clientloop.c:1310
核心工作原理
- ssh,作为客户端:
- 逻辑主要循环读取 终端T, 加密传给sshd, 读取网络包,解密写入T。
写入T之后,在屏幕上显示什么是T的write的效果,与ssh无关。- T就是你启动ssh的终端,它可能是tty也可能xterm模拟的pts,甚至有可能是串口。
- 如果是putty/xmobaterm之类在Windows的客户端就不读终端,而是读窗口消息
- sshd,作为服务端:
- accept(得到连接L)+fork(得到S)之后
- 认证身份
- S创建伪终端
/dev/pts/n并用dup2重定向其stdin, stdout - S再fork一个bash继承文件表
- S循环直到网络断开
- 读取L, 解密,并写入stdout(
/dev/pts/n) - 读取stdin(
/dev/pts/n),加密,并写入L(转发回ssh)
- 读取L, 解密,并写入stdout(
- bash:
- S启动bash时,已经将stdin,stdout偷换了。当然bash不关心这个也感知不到这个。
- bash本身的逻辑就是循环读写stdin, stdout并执行读到的命令。
sshd的本质是通过加密的网络连接将客户的终端T映射成服务器的终端pts/n
sshd的主要工作:
- 处理网络连接:建立安全的通信通道
- 用户认证:
- 支持多种认证方式,包括密码、公共密钥、双因素认证。
- 没错,用户认证是sshd做的,不是系统功能。
- 认证之后就能创建session了。以相应的用户来运行bash。
- 授权与访问控制:
- /etc/ssh/sshd_config
- 分配伪终端:
- 为每个新连接分配一个伪终端设备(/dev/pts/n)。
- 管理与伪终端的读写过程,将网络上的数据传递给终端(与bash交互),同时将终端输出传回客户端。
- 命令执行:bash,其他命令是bash间接执行的
SSH 协议
SH 协议有两个主要版本:SSH-1 和 SSH-2。现代系统大多使用 SSH-2。
ssh的行为
sshd的行为
sshd 接收到来自 SSH 客户端的加密数据包之后
- 数据解析
- 解码数据包:sshd 首先解密接收到的数据包,提取出实际的内容(如输入的字符)。
- 确定数据类型:解析数据包后,sshd 会确定数据的类型,通常是一个 "data" 消息或 "channel request"。
- 输入处理
- 将字符传递给 shell:如果输入是字符,sshd 会将这些字符传递给与该会话关联的 shell。
- 这通过标准输入(stdin)实现,sshd 将字符重定向到 shell 的输入流。
- 执行命令
- bash 或其他 shell 接收到字符后,会根据输入解析命令。如果输入是完整的命令,shell 会执行该命令。
- 执行命令后,shell 会生成输出(如命令的结果或错误信息)。
- 输出返回
- bash 将输出写入标准输出(stdout),sshd 会捕获这些输出,并通过加密通道将其发送回 SSH 客户端。
- 输出格式化:如果有必要,sshd 还会进行格式化,以确保输出在客户端正确显示。
- 处理信号
- sshd 会处理来自客户端的信号(如 Ctrl+C),并将这些信号转发给相应的 shell,以便用户能够中断或终止正在运行的命令。
- 会话管理
- sshd 还会监控会话的状态,管理用户的会话生命周期,包括处理连接的断开、超时等情况。
pxf_god@pxf-ubuntu:~$ pstree
systemd─┬─ModemManager───2*[{ModemManager}]
├─agetty
....
├─snapd───13*[{snapd}]
├─sshd─┬─sshd───sshd───bash───pstree
│ ├─sshd───sshd───sftp-server
│ └─sshd───sshd───bash─┬─sh───node─┬─node─┬─bash
│ │ │ └─11*[{node}]
│ │ ├─node─┬─cpptools───13*[{cpptools}]
│ │ │ └─11*[{node}]
│ │ ├─node───12*[{node}]
│ │ └─10*[{node}]
│ └─sleep
pxf_god 15874 15829 0 14:18 ? 00:00:00 sh /home/pxf_god/.vscode-server/bin/74f6148eb9ea00507ec113ec51c489d6ffb4b771/bin/code-server --start-server --host=127.0.0.1 --accept-server-license-terms --enable-remote-auto-shutdown --port=0 --telemetry-level all --connection-token-file /home/pxf_god/.vscode-server/.74f6148eb9ea00507ec113ec51c489d6ffb4b771.token
pxf_god 15884 15874 3 14:18 ? 00:00:03 /home/pxf_god/.vscode-server/bin/74f6148eb9ea00507ec113ec51c489d6ffb4b771/node /home/pxf_god/.vscode-server/bin/74f6148eb9ea00507ec113ec51c489d6ffb4b771/out/server-main.js --start-server --host=127.0.0.1 --accept-server-license-terms --enable-remote-auto-shutdown --port=0 --telemetry-level all --connection-token-file /home/pxf_god/.vscode-server/.74f6148eb9ea00507ec113ec51c489d6ffb4b771.token
pxf_god@pxf-ubuntu:~/labs/openssh-portable$ file /home/pxf_god/.vscode-server/bin/74f6148eb9ea00507ec113ec51c489d6ffb4b771/bin/code-server
/home/pxf_god/.vscode-server/bin/74f6148eb9ea00507ec113ec51c489d6ffb4b771/bin/code-server: a /usr/bin/env sh script, ASCII text executable
ssh问题排查
-
sshd的配置文件在
/etc/ssh/sshd_config -
重启sshd服务
- ubuntu
sudo service ssh restart - centos
sudo systemctl restart sshd - archlinux
sudo systemctl restart sshd - macOS
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
- sshd的日志在
- ubuntu
sudo tail -f /var/log/auth.log - centos
sudo tail -f /var/log/secure - archlinux
sudo journalctl -u sshd/sudo journalctl -u sshd -f - macOS
sudo tail -f /var/log/system.log
无法private-key免密码登录
- 检查客户端是否勾了 private-key
- 查看日志
Accepted publickey for xxx from 192.168.10.3 port 59787 ssh2: RSA SHA256:xoMbWzQcoHGF0vBpRel2b1QsSGqZUNXiM5QzXBZ99N0
error: AuthorizedKeysCommand path is not absolute

浙公网安备 33010602011771号