首页 > 代码库 > Android上sshd的使用

Android上sshd的使用

1. 介绍

因为某些原因, 笔者需要在android上开发,  使用adb比较麻烦, 于是想使用sshd.

推荐的软件是openssh, 其他选择有dropbear, mosh.
当然还有其他选择, 如termux, 这里不予讨论

2. 编译配置

在Android中已经有openssh包, 位于external/openssh
默认openssh没有编译进Android系统, 需要进行配置

2.1 openssh模块

首先我们要了解Android中程序都是以模块(PACKAGES)的形式唯一存在的
我们按照既定的规则在模块中添加Android.mk的文件, 通过LOCAL_MODULE来定义
对于openssh, 它包含了如下模块

scp, sftp, ssh, sshd, sshd_config, ssh-keygen, start-ssh
<style></style>

2.2 Android编译系统

其次就是需要我们将openssh模块添加到Android的编译系统中去
而所有需要编译进Android中的模块则通过PRODUCT_PACKAGES变量来定义

Android在编译时候通常通过lunch在制定target
以bpi为例, 使用的命令是lunch mars_a31s-eng
而mars_a31s-eng则在device/softwinner/mars-a31s/vendorsetup.sh中定义

add_lunch_combo mars_a31s-eng
<style></style>

而该target又制定了总Makefile, 位于device/softwinner/mars-a31s/AndroidProducts.mk

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/mars_a31s.mk
<style></style>

mars_a31s.mk又包含了其他林林总总的Makefile, 其中就包含了device/softwinner/fiber-common/fiber-common.mk
我们就把openssh模块添加到fiber-common.mk文件中

在fiber-common.mk中新增如下内容

# Openssh
PRODUCT_PACKAGES += \
    scp \
    sftp \
    ssh \
    sshd \
    sshd_config \
    ssh-keygen \
    start-ssh
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

然后重新编译Android系统

2.3 openssh文件

编译完成后烧录或者刷机后, 可以看到文件系统中openssh的文件分别在如下位置(CM中有所不同)

/system/bin/ssh
/system/bin/ssh-keygen
/system/bin/sshd
/system/bin/start-ssh
/system/bin/scp
/system/bin/sftp
/system/etc/ssh/sshd_config
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style><style></style>

3. openssh配置

在Linux中使用ssh我们一般都是采用username/password的方式
但是在Android中是没有这一概念的, 当然可以通过修改源码或者添加伪用户的方式
笔者这里采用的是ssh的另一个使用方法即使用密钥登录登录

注意: 以下命令均在root下执行

3.1 创建目录结构

mkdir -p /data/ssh/empty
chmod 700 /data/ssh
chmod 700 /data/ssh/empty
<style></style>

其中, /data/ssh用来存放密钥文件和sshd配置文件

3.2 生成配置文件

cat /system/etc/ssh/sshd_config | \
    sed ‘s/#PermitRootLogin yes$/PermitRootLogin without-password/‘ | \
    sed ‘s/#RSAAuthentication yes/RSAAuthentication yes/‘ | \
    sed ‘s/#PubkeyAuthentication yes/PubkeyAuthentication yes/‘ | \
    sed ‘s/PasswordAuthentication no/#PasswordAuthentication no/‘ | \
    sed ‘s/#PermitEmptyPasswords no/PermitEmptyPasswords yes/‘ | \
    sed ‘s/#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication yes/‘ | \
    sed ‘s/#UsePrivilegeSeparation yes/UsePrivilegeSeparation no/‘ | \
    sed ‘s;/usr/libexec/sftp-server;internal-sftp;‘ > \
    /data/ssh/sshd_config
chmod 600 /data/ssh/sshd_config

这里需要说明的是我们需要配置为root使用, 同时又不需要密码.

另外, 需要注意配置文件中指定了AuthorizedKeysFile为/data/ssh/authorized_keys

3.3 生成密钥

在Windows/Linux上通过下面的命令来生成密钥

ssh-keygen -t rsa -C "your_email_address
<style></style>

上面的命令会在主目录下生成.ssh目录, 目录包含id_rsa(私钥)和id_rsa.pub(公钥)两个文件

然后通过adb等命令将id_rsa.pub上传至Android中(!!!文件要对应于AuthorizedKeysFile!!!)

adb push id_rsa.pub /data/ssh/authorized_keys
chmod 600 /data/ssh/authorized_keys
chown root:root /data/ssh/authorized_keys
<style></style>

3.4 生成启动脚本

mkdir -p /data/local/userinit.d
cat /system/bin/start-ssh | \
    sed ‘s;/system/etc/ssh/sshd_config;/data/ssh/sshd_config;‘ > \
    /data/local/userinit.d/99sshd
chmod 755 /data/local/userinit.d/99sshd
<style></style>

通过上面的命令单独生成一个启动脚本
然后就可以通过执行下面的脚本来启动sshd

/data/local/userinit.d/99sshd
<style></style>

实际操作过程中如果出现问题也可以通过下面的命令以调试的方式来启动sshd

/system/bin/sshd -f /data/ssh/sshd_config -D -ddd
<style></style>

3.5 连接sshd

使用命令即可连接sshd

ssh root@ip
<style></style>

需要注意的是在Windows下使用ssh客户端时需要配置使用密钥登录选项, 并指定密钥文件
具体选项的位置则依据工具的不同而不同

同理SFTP和SCP登录也如此
笔者发现WinSCP由于没有可配置项导致无法成功连接SFTP, 而FileZilla则可以

4. sshd自启动

现在sshd已经可以成功运行并登录, 接下来需要做的则是让sshd可以自启动

4.1 修改init.rc

这是最直接的办法, 问题在于init.rc是由boot.img动态生成的initramfs而产生
故而即使在已经运行的文件系统中修改了, 重启后还是会恢复原来的内容
那么就只能在源代码中修改后再行编译

找到system/core/rootdir/init.rc, 发现已经包含了sshd的内容, 只是默认被禁用了, 而且启动方式也不是我们期望的

service sshd /system/bin/start-ssh
    class main
    disable

将init.rc修改为

service sshd /system/bin/start-ssh
    class main
    user  root
    group root
<style></style>

4.2 其他文件

另外需要修改的文件包括如下external/openssh/start-ssh和external/openssh/sshd_config.android

具体的修改内容可以参考前文描述

参考:
<Sshd howto for CM>
<理解Android Build系统>
<Android启动过程深入解析>
<从CM刷机过程和原理分析Android系统结构>

Android上sshd的使用