因为某些原因, 笔者需要在android上开发, 使用adb比较麻烦, 于是想使用sshd. 推荐的软件是openssh, 其他选择有dropbear, mosh. 在Android中已经有openssh包, 位于external/openssh;默认openssh没有编译进Android系统, 需要进行配置 2.1 openssh模块首先我们要了解Android中程序都是以模块(PACKAGES)的形式唯一存在的 scp, sftp, ssh, sshd, sshd_config, ssh-keygen, start-ssh 2.2 Android编译系统其次就是需要我们将openssh模块添加到Android的编译系统中去 Android在编译时候通常通过lunch在制定target add_lunch_combo mars_a31s-eng 而该target又制定了总Makefile, 位于device/softwinner/mars-a31s/AndroidProducts.mk
PRODUCT_MAKEFILES := \ mars_a31s.mk又包含了其他林林总总的Makefile, 其中就包含了device/softwinner/fiber-common/fiber-common.mk 在fiber-common.mk中新增如下内容
# Openssh 然后重新编译Android系统 2.3 openssh文件编译完成后烧录或者刷机后, 可以看到文件系统中openssh的文件分别在如下位置(CM中有所不同)
/system/bin/ssh 在Linux中使用ssh我们一般都是采用username/password的方式 注意: 以下命令均在root下执行 3.1 创建目录结构
mkdir -p /data/ssh/empty 其中, /data/ssh用来存放密钥文件和sshd配置文件 3.2 生成配置文件
cat /system/etc/ssh/sshd_config | \ 这里需要说明的是我们需要配置为root使用, 同时又不需要密码. 另外, 需要注意配置文件中指定了AuthorizedKeysFile为/data/ssh/authorized_keys 3.3 生成密钥在Windows/Linux上通过下面的命令来生成密钥 ssh-keygen -t rsa -C "your_email_address" 上面的命令会在主目录下生成.ssh目录, 目录包含id_rsa(私钥)和id_rsa.pub(公钥)两个文件 然后通过adb等命令将id_rsa.pub上传至Android中(!!!文件要对应于AuthorizedKeysFile!!!)
adb push id_rsa.pub /data/ssh/authorized_keys
mkdir -p /data/local/userinit.d 通过上面的命令单独生成一个启动脚本 /data/local/userinit.d/99sshd 实际操作过程中如果出现问题也可以通过下面的命令以调试的方式来启动sshd /system/bin/sshd -f /data/ssh/sshd_config -D -ddd 3.5 连接sshd使用命令即可连接sshd ssh root@ip 需要注意的是在Windows下使用ssh客户端时需要配置使用密钥登录选项, 并指定密钥文件 同理SFTP和SCP登录也如此, 需要制定密钥文件 4. 自启动现在sshd已经可以成功运行并登录, 接下来需要做的则是让sshd可以自启动 4.1 修改init.rc这是最直接的办法, 问题在于init.rc是由boot.img动态生成的initramfs而产生 找到system/core/rootdir/init.rc, 发现已经包含了sshd的内容, 只是默认被禁用了, 而且启动方式也不是我们期望的
service sshd /system/bin/start-ssh 将init.rc修改为
service sshd /system/bin/start-ssh NOTE: 除了修改init.rc外, 为了让sshd能够正常自启动 具体的修改内容可以参考前文描述 TIP: 上面的做法对于没有selinux的Android版本正常工作, 但是一旦有了selinux则发现如下错误
[ 155.996453] c0 init: Warning! Service sshd needs a SELinux domain defined; please fix! [ 156.004202] c0 init: Starting service 'sshd'... [ 156.008591] c0 init: cannot execve('/system/bin/start-ssh'): Permission denied [ 156.014985] c0 type=1400 audit(1480673531.748:53): avc: denied { execute_no_trans } for pid=4073 comm="init" path="/system/bin/star t-ssh" dev=mmcblk0p9 ino=402 scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 tclass=file permissive=0 需要添加为start-ssh添加sepolicy /system/bin/sysinit u:object_r:sysinit_exec:s0 然后创建vendor/cm/sepolicy/sysinit.te文件, 在该文件中声明相关权限 4.2 其他方式(不成功)在笔者使用的CM系统中, 就出现了由于selinux导致的权限问题 查看启动log后发现CM在启动的时候会执行/system/bin/sysinit脚本 创建/data/local/userinit.sh文件, 内容如下
#!/system/bin/sh 修改userinit.sh的权限 chmod 755 /data/local/userinit.sh 然后按照3.4章节生成/data/local/userinit.d/99sshd作为sshd的启动脚本 因为userinit.sh需要读取目录和文件执行, 需要修改它的domain, 改为和sysinit一样 /data/local/userinit.sh u:object_r:userinit_data_exec:s0 ---> /data/local/userinit.sh u:object_r:userinit_exec:s0 同时需要为/data/local/userinit.d目录下所有文件增加权限 /data/local/userinit.d(/.*)? u:object_r:userinit_exec:s0 注: 上面的方法不成功, 一直提示如下错误 12-02 22:42:39.370 1 1 W init : type=1400 audit(0.0:4): avc: denied { relabelto } for name="userinit.sh" dev=mmcblk0p10 ino=81928 scontext=u:r:init:s0 tcontext=u:object_r:userinit_exec:s0 tclass=file permissive=0 似乎sepolicy比较麻烦, 必须单独配置, 这里不再深究, 还是采用init.rc的方法简单明了 配置sepolicy的方法可参考<Android下添加自启动应用Android下添加自启动应用> 5. 其他配置 5.1 shell通过ssh登录后, 发现当前shell与系统的shell是有一些不同的, 同时如果我们需要配置一些环境变量的话又不知从何入手 创建HOME目录
mkdir /data/home 然后在HOME目录下创建一个脚本/data/home/login, 内容如下
#!/system/xbin/bash 修改该脚本的权限 chmod 755 /data/home/login 然后每次登陆后执行执行下面这条命令 exec /data/home/login 同时在/data/home/目录下创建.bash_profile, 内容如下 if [ -f /etc/bash/bashrc ]; then . /etc/bash/bashrc fi unset HOME HOME=/data/home LD_LIBRARY_PATH=.:/vendor/lib:/system/lib PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin ANDROID_DATA=/data ANDROID_ROOT=/system export PS1 HOME HOSTNAME LD_LIBRARY_PATH PATH ANDROID_DATA ANDROID_ROOT 其中, bash默认会导入~/.bash_profile作为环境变量, 这里另外导入了/etc/bash/bashrc ------------------------------------------------------------------------------------------- 了解发现, mksh会导入全局文件/profile作为环境变量 显然这些我们都无法使用, 笔者的方案是自行导入一个文件作为环境变量
HOME=/data/home NOTE: 笔者使用的Android中, 发现很多命令在执行时需要加上busybox前缀, 查阅后了解到时这些命令到链接到toolbox的缘故 比较常见的修改方式使用busybox --install命令安装到PATH中 在上面提到的.shrc加上如下内容 # for busybox for n in $(busybox --list) do eval alias $n=\'busybox $n\' done 参考: |