SSH&SCP移植和使用参考


1. 移植

SSH(Secure Shell)和SCP(Secure Copy)是与远程登录相关协议和安全文件传输的工具。

SSH是一种加密的网络协议,用于安全地远程登录到远程计算机或在计算机之间建立安全的通信连接。SSH通过在网络上建立加密的会话,提供了对远程计算机的安全访问。

SCP是基于SSH协议的文件传输工具,用于在本地计算机和远程计算机之间进行安全的文件传输。

SSH和SCP工具属于OpenSSH包,编译时依赖于OpenSSL、Zlib,因此在交叉编译工具前需要交叉编译OpenSSL和Zlib,版本说明如下:

  • OpenSSH: 8.3p1
  • OpenSSL: 1.1.1i
  • Zlib: 1.2.12

1.1. 传统方式

1.1.1. OpenSSL交叉编译

OpenSSL是一个开源的软件库,提供了一组用于安全通信的密码学功能和工具,广泛用于安全协议的实现、加密通信的建立以及数字证书的管理。

1.1.1.1. 源码下载

OpenSSL下载地址

版本:1.1.1i

1.1.1.2. 交叉编译

资源包下载完成后,解压进入opensl-1.1.1i目录,执行Configure配置文件配置编译工具链和指定相应的安装路径,如下:

tar -zxvf openssl-1.1.1i.tar.gz
cd openssl-1.1.1i/
export PATH=/tools/toolchain/gcc-10.2.1-20210303-sigmastar-glibc-x86_64_aarch64-linux-gnu/bin:$PATH ; export ARCH=arm64 ; export CROSS_COMPILE=aarch64-linux-gnu-
./Configure --prefix=$PWD/install linux-aarch64
make clean -j8
make -j8
make install

注意上述示例步骤中的export命令指定的编译链地址,实际操作时请根据真实的编译链路径进行声明。执行上述步骤后将在openssl-1.1.1i/install/路径下找到生成的头文件和库文件。

1.1.2. Zlib交叉编译

Zlib是一个开源的数据压缩库,提供了高效的压缩和解压功能。

1.1.2.1. 源码下载

Zlib下载地址

版本:1.2.12

1.1.2.2. 交叉编译

资源包下载完成后,解压进入zlib-1.2.12目录,执行configure文件配置安装目录,如下:

tar -xvf zlib-1.2.12.tar.xz
cd zlib-1.2.12/
export PATH=/tools/toolchain/gcc-10.2.1-20210303-sigmastar-glibc-x86_64_aarch64-linux-gnu/bin:$PATH ; export ARCH=arm64 ; export CROSS_COMPILE=aarch64-linux-gnu-
./configure --prefix=$PWD/install/ --enable-shared
make clean -j8
make -j8
make install

注意上述示例步骤中的export命令指定的编译链地址,实际操作时请根据真实的编译链路径进行声明。执行上述步骤后将在zlib-1.2.12/install/路径下找到生成的头文件和库文件。

1.1.3. SSH&SCP交叉编译

OpenSSH(Open Secure Shell)是一个开源的网络协议和工具集,用于安全地远程登录和数据传输,是SSH协议的实现之一,提供了加密的通信和身份验证机制,以确保远程访问的安全性。

1.1.3.1. 源码下载

OpenSSH下载地址

版本:8.3p1

1.1.3.2. 交叉编译

资源包下载完成后,解压进入openssh-8.3p1目录,执行configure文件配置编译选项,如下:

tar -zxvf openssh-8.3p1.tar.gz
cd openssh-8.3p1/
export PATH=/tools/toolchain/gcc-10.2.1-20210303-sigmastar-glibc-x86_64_aarch64-linux-gnu/bin:$PATH ; export ARCH=arm64 ; export CROSS_COMPILE=aarch64-linux-gnu-
./configure --host=aarch64-linux-gnu --with-libs --with-zlib=$PWD/../zlib-1.2.12/ --with-ssl-dir=$PWD/../openssl-1.1.1i/ --exec-prefix=/customer/ssh --prefix=$PWD/install --disable-etc-default-login --disable-strip CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar
make clean -j8
make -j8

编译选项说明:

  • --prefix: 将体系无关文件安装到目录PREFIX里,默认是/usr/local,这里指定为./install目录
  • --with-zlib: Zlib安装路径
  • --with-ssl-dir: OpenSSL安装路径
  • --host: 交叉编译出来的程序运行的平台

原有生成的程序大小较大,可以通过如下命令进行裁剪:

aarch64-linux-gnu-strip ssh --strip-unneeded
aarch64-linux-gnu-strip sshd --strip-unneeded
aarch64-linux-gnu-strip scp --strip-unneeded

通过该方式构建出来的程序依赖libz.so.1、libcrypt.so.1、libcrypto.so.1.1、libutil.so.1库。

1.2. 基于Buildroot

SSH和SCP属于OpenSSH包,版本为8.3p1,按如下步骤可直接编译构建:

export PATH=/tools/toolchain/gcc-10.2.1-20210303-sigmastar-glibc-x86_64_aarch64-linux-gnu/bin:$PATH ; export ARCH=arm64 ; export CROSS_COMPILE=aarch64-linux-gnu-
cd 3rdparty/buildroot-masters
make openssh

通过该方式构建出来的sshd依赖libselinux.so.1、libpcre.so.1,相关lib库集成在3rdparty/buildroot-master/output/target/usr/lib/文件夹下。


2. 环境搭建

2.1. 拷贝文件

创建一个target目录,放在与openssh-8.3p1同级下,目录结构:

  • target
    • etc
    • lib
    • sbin

(1) 进入完成编译的openssh-8.3p1目录下,拷贝资源,执行命令如下:

cd openssh-8.3p1/
cp moduli ssh_config sshd_config ../target/etc
cp sshd scp ssh-keygen ../target/sbin

(2) 相关库文件拷贝,执行命令如下:

从toolchain安装目录中相关库文件到/target/lib目录下,分别有:

cd /tools/toolchain/gcc-10.2.1-20210303-sigmastar-glibc-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/libc/
cp ./lib/libcrypt.so.1 target/lib
cp ./lib/libresolv.so.2 target/lib
cp ./lib/libutil.so.1 target/lib
cp ./lib/libnss_files.so.2 target/lib
cp ./lib/libnss_compat.so.2 target/lib

再将libcrypto.so.1.1、libz.so.1、libssl.so.1.1等依赖库一并拷贝到目录下。

2.2. 文件打包和启动配置

(1) 在project\release\chip\pcupid\dispcam\common\glibc\10.2.1\release\bin\debug目录下新建一个ssh文件夹,将target目录下的sbin、etc、lib四个文件夹拷贝到工程代码里project\release\chip\pcupid\dispcam\common\glibc\10.2.1\release\bin\debug目录下,代码工程编译时会自动拷贝到/customer目录下。

(2) 修改target/etc/sshd_config,指定ssh_host_rsa_key、ssh_host_dsa_key默认路径和PermitEmptyPasswords参数

-#HostKey /etc/ssh/ssh_host_rsa_key
-#HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /customer/ssh/etc/ssh_host_rsa_key
+HostKey /customer/ssh/etc/ssh_host_dsa_key
...
-#PermitEmptyPasswords yes
+PermitEmptyPasswords yes

(3) 修改rootfs分区打包的脚本:

  1. 修改root用于默认密码为1234,用于ssh登陆;

    板子上使用的passwd root命令,密码为1234,系统会更改/etc/passwd文件,将/etc/passwd文件中的root一行拷贝即为root用户密码配置;

    PS:要使用passwd root命令时,编译sdk配置rootfs不能为squashfs系统,squashfs为只读系统,passwd命令无法修改/etc/passwd文件

  2. 添加sshd用户,不然sshd启动会报错Privilege separation user sshd does not exist,即增加sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin,参考修改内容如下:


3. 测试验证

在板端执行命令生成key值和拷贝相关的资源:

/customer/ssh/sbin/ssh-keygen -t rsa -f ssh_host_rsa_key -N ""
/customer/ssh/sbin/ssh-keygen -t dsa -f ssh_host_dsa_key -N ""
/customer/ssh/sbin/ssh-keygen -t ecdsa -f ssh_host_ecdsa_key -N ""

将ssh_host_*_key从板端用其他工具传出拷贝至/target/lib下,以便下次打包免去这步操作,同时也一并拷贝至板端的/customer/ssh/etc目录下开始本次测试验证。

输入ifconfig eth0 xx.xx.xx.xx配置与PC主机同网段的IP地址后,确认可以互相ping通,即可使用命令/customer/ssh/sbin/sshd -f /customer/ssh/etc/sshd_config进行测试验证。

3.1. ssh验证

3.1.1. 基于Windows命令行

打开windows cmd,输入 ssh -t root@xx.xx.xx.xx,能够正常访问到设备shell的话,代表连接成功。

3.1.2. 基于XShell工具

成功连接进板端后,能够通过ps命令查看到创建的ssh进程:

同时在XShell会话可以输入rz/sz进行文件传输:

由于是基于网络进行的ssh交互,因此文件传输速度比起UART快很多。

3.2. scp验证

3.2.1. 基于Windows命令行

打开cmd或者xshell,输入 scp root@xx.xx.xx.xx,PC机能够与板端进行文件上传或者下载,代表scp使用正常。

3.2.2. 基于WinSCP

打开WinSCP:

能够正常连接到板端,通过左右拖拽进行文件交互:


4. 常用Q&A

Q1:使用scp时,报错Could not chdir to home directory /home/root:No such file or directory

此问题不影响scp的正常使用,可忽略。板子端做远端时,账号密码信息没有保存到/home目录下,需要把远端服务器rootfs改成可写文件系统,在/home下创建对应账号文件夹,scp会创建如下路径和文件且保存密钥。

Q2: 本地有scp命令或scp运行文件,但还是报sh:scp:not found

此报错是指远端sh命令中没有scp,并不是指本地。scp会通过ssh给远端下scp cmd,从code中加打印可以看到命令如下:

板子做远端时,busybox下没有scp命令,所以执行此命令时会报找不到sh命令错误。在rootfs.mk加如上内容,打包的时候会把scp加到/bin下,可以在任意路径执行scp,解决报错问题。

Q3: 执行scp时板子上有libutil.so.1等scp依赖库,也声明了路径,把声明加到了/etc/profile和/etc/init.d/rcS,但还是会报无法打开库的错误

scp源码链接路径写死了,依赖的几个so库要放在rootfs的/lib目录下。在rootfs.mk加如上内容,打包的时候会把对应库打包到/lib下,解决如上报错。

Q4: SSH访问root账号时,弹出拒绝密码

设置/customer/ssh/etc/sshd_config中PermitEmptyPasswords yes;PermitRootLogin yes;StrictModes yes即可。