各位看官,小子我先问个问题:是不是经常在容器里想开个SSH,却发现自己不是root,处处碰壁?这是常态。多数容器镜像精简到连SSH服务都没有,就算有,咱们普通用户也没权限启动它。
今天小子就介绍一下自己的小经验,以供各位看官参考:自己动手,编译运行 openssh-portable
。这是OpenSSH官方提供的可移植版本,堪称神器。
当然,条条大路通罗马。您也可以用Go或Python写的SSH库,或者找现成的二进制包。但小子我认为,自己编译,最稳当,也最能掌控全局。
第一步:铸剑(编译 OpenSSH)
咱们得先有兵器。这个过程就像炼一把自己的剑,得心应手。
如果已经有了sshd及相关程序,但没有root用户权限,可以省去编译这个步骤。
1. 备料与取源
您得有gcc
, make
, zlib
和openssl
的开发库。在容器里缺啥就补啥。然后,去官网下载源码包并解压。
bash
# 例如:下载并解压
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-10.0p2.tar.gz
tar -xzvf openssh-10.0p2.tar.gz
cd openssh-10.0p2
bash
# 也可从github上克隆编译
git clone https://github.com/openssh/openssh-portable # or https://anongit.mindrot.org/openssh.git
cd openssh-portable
autoreconf
2. 开炉锻造(配置与编译)
这是最关键的一步!配置时,必须用--prefix
指定一个我们自己的地盘,比如$HOME/my_openssh
。
常规锻造法(推荐):
bash
./configure --prefix=$HOME/my_openssh --without-pam
make && make install
--prefix
: 这是咱们的护身符,它保证了make install
只会把文件安装到您指定的地方,绝对不会染指系统目录。--without-pam
: 明确禁用PAM。在容器里,我们通常用不到它,禁用可以减少不必要的依赖和潜在问题。
特殊锻造法(备用方案):
当您碰到一些没有openssl
开发库的"老古董"环境时,这个参数能救命。
bash
./configure --prefix=$HOME/my_openssh --without-pam --without-openssl
--without-openssl
: 这个参数的代价是牺牲大量的现代加密算法。这是为了解决"有没有"问题的妥协方案,非万不得已,不要在生产环境使用。
3. 宝剑开锋(生成主机密钥)
用刚出炉的ssh-keygen
生成服务器的身份密钥。
bash
# 确保配置目录存在
mkdir -p $HOME/my_openssh/conf
# 生成密钥,-f 指定路径要和后面配置文件里的一致
$HOME/my_openssh/bin/ssh-keygen -t ed25519 -f $HOME/my_openssh/conf/ssh_host_key -N ""
第二步:心法(详解配置文件)
配置文件是sshd
的灵魂。配置文件一般名称为/etc/ssh/sshd_config,当然也可以使用其它名称放到其它路径下。
小子我把整本《心法秘籍》的主要章节都给您念念。
第一章:监听与路径(安身立命之本)
Port 28022
# 必须是绝对路径,不能带环境变量(下同)
HostKey /home/appuser/my_openssh/conf/ssh_host_key
PidFile /tmp/sshd-custom.pid
第二章:认证(验明正身之法)
StrictModes no
PubkeyAuthentication yes
PasswordAuthentication yes
PermitEmptyPasswords yes
ChallengeResponseAuthentication no
UsePAM no
PermitRootLogin yes
第三章:会话与子系统(待客之道)
# 这是提供sftp服务的关键,路径指向我们编译出的 sftp-server
Subsystem sftp /home/appuser/my_openssh/sftp-server
# --- 重点中的重点 ---
# 以下两个是小子我踩过坑才找到的宝贝。没有它们,客户端可能连不上!
# 它们指向编译时生成的辅助程序,用于处理会话和认证的内部流程。
# 路径同样是绝对路径
SshdSessionPath /home/appuser/my_openssh/sshd-session
SshdAuthPath /home/appuser/my_openssh/sshd-auth
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
第四章:日志(明察秋毫之术)
# INFO, DEBUG1, 2, 3
LogLevel DEBUG3
第五章:权限(不可逾越的红线)
看官请务必记住:sshd
对权限极为敏感! 这是安全的基石,也是新手最容易出错的地方。
- 服务器密钥 : 存放
HostKey
的那个文件,权限必须是600
。这意味着只有您自己(运行sshd
的用户)可读可写。 - 用户公钥 : 客户端的公钥文件
~/.ssh/authorized_keys
,权限必须是600
。 - .ssh目录 : 存放
authorized_keys
的.ssh
目录,权限必须是700
。
如果权限不对,sshd
会直接拒绝使用这些文件,而且往往不会给出非常直白的错误信息,导致您百思不得其解。
第三步:点火(启动与运行)
万事俱备,只欠东风。创建一个启动脚本,如start-sshd.sh。
bash
#!/bin/bash
MY_OPENSSH_HOME=$HOME/my_openssh
# --- 重点:在启动前,确保所有密钥权限正确! ---
# 这是sshd的强制要求,权限不对,服务起不来或连不上
chmod 700 $HOME/.ssh
chmod 600 $HOME/.ssh/authorized_keys
chmod 600 $MY_OPENSSH_HOME/conf/*
# 如果日志目录不存在,则创建
mkdir -p $MY_OPENSSH_HOME/logs
# 启动命令,
$MY_OPENSSH_HOME/sshd \
-f $MY_OPENSSH_HOME/conf/opensshd.conf \
-E $MY_OPENSSH_HOME/logs/sshd.log
第四步:迎客(配置客户端公钥)
服务器跑起来了,怎么在客户端登录呢?
- 使用密码登录
bash
ssh appuser@ip -p 28022
# 输入密码
- 使用密钥登录
-
方法一:远程命令发送公钥
如果您的客户端有
ssh-copy-id
命令,这是最简单稳妥的方式。它会自动完成所有操作,包括设置正确的权限,但这是个悖论,因为新安装的sshd还没有用户可以连接,一般会使用手工上传公钥的方式(见下文)bash# 在您的客户端机器上运行,它会把您的公钥(如~/.ssh/id_rsa.pub)上传到服务器 # -p 28022 指定我们自定义的端口 ssh-copy-id -i ~/.ssh/id_rsa.pub "-p 28022 user@your_server_ip"
-
方法二:手工上传
如果没法用
ssh-copy-id
,就只能自己动手了。- 首先,用密码登录到您的服务器上(或者其它办法)。
- 在服务器上,执行以下操作:
bash# 确保.ssh目录存在,并设置正确权限 700(如果已经做过就不用重复执行) mkdir -p ~/.ssh chmod 700 ~/.ssh # 将您客户端的公钥内容,粘贴到 authorized_keys 文件中 # 注意用 >> 追加,不要用 > 覆盖 echo "ssh-rsa AAAA..." >> ~/.ssh/authorized_keys # --- 最后,也是最关键的一步:设置authorized_keys的权限为 600!--- chmod 600 ~/.ssh/authorized_keys
-
登录
bashssh -i your_pub_keyfile appuser@ip -p 28022
-
好了,各位看官,这回的终极宝典应该算是面面俱到了。从铸剑到心法,再到点火迎客,以及那些决定成败的权限细节,都已尽数奉上。希望小子我的这点经验,能为各位看官披荆斩棘。祝您折腾愉快!