This Magisk module contains OpenSSH 10.0p2 using the libraries from OpenSSL 3.5.4 for Android

ASUS_I006D:/ $ ASUS_I006D:/ $ sshd -V
OpenSSH_10.0p2, OpenSSL 3.5.4 30 Sep 2025
ASUS_I006D:/ $ 

ASUS_I006D:/ $ ssh -V
OpenSSH_10.0p2, OpenSSL 3.5.4 30 Sep 2025
ASUS_I006D:/ $ 


These OpenSSH binaries are compiled with SELinux support.


All binaries are dynamically linked for the default Android libraries only , e.g:

ASUS_I006D:/ $ ldd /system/bin/sshd
	linux-vdso.so.1 => [vdso] (0x77aef25000)
	libdl.so => /apex/com.android.runtime/lib64/bionic/libdl.so (0x77ab56e000)
	libc.so => /apex/com.android.runtime/lib64/bionic/libc.so (0x77ab432000)
ASUS_I006D:/ $ 

ASUS_I006D:/ $ ldd /system/bin/ssh                                                                                                                                                       
	linux-vdso.so.1 => [vdso] (0x7d03cf9000)
	libdl.so => /apex/com.android.runtime/lib64/bionic/libdl.so (0x7cfe54c000)
	libc.so => /apex/com.android.runtime/lib64/bionic/libc.so (0x7cfe40c000)
ASUS_I006D:/ $ 


To automatically start the sshd after a reboot create the file

/data/local/tmp/home/start_sshd

To define additional parameter for the automatic start of the sshd, save these parameter in the file

/data/local/tmp/home/.ssh/sshd_parameter


To write the messages from the script service.sh to the log file

/data/local/tmp/var/log/sshd.log

create the file

/data/local/tmp/debug


The default port by the sshd is 9022:

ASUS_I006D:/ $ grep -i 9022 /etc/ssh/sshd_config                                                                                                                                                                      
Port 9022
ASUS_I006D:/ $ 


Compile details
---------------

The configure options used are copied from the Termux Build script for OpenSSH:

    https://github.com/termux/termux-packages/blob/master/packages/openssh/build.sh

The configure command used to create the config for Compiling OpenSSH in Android is in the file

   source/myconfigure

in the Magisk Module

All patches for OpenSSH from Termux that are useful for a Magisk Module with OpenSSH are applied to the source code.

The patches for OpenSSH in Termux are available here:

    https://github.com/termux/termux-packages/tree/master/packages/openssh

The patches used are in the directory ./source/patches in the Magisk Module; the patches were copied from the repo at 2024-10-04.
The script source/patches/apply_patches.sh can be used to apply the patches.

An additional patch was necessary to get the OpenSSH binaries working for the user shell:

Source: https://stackoverflow.com/questions/76376942/openssh-9-3p-fails-to-build-for-android
(This is the patch misc.c.additional.patch in the directory source/patches in this Magisk Module)

 ----

2024-01-31 I've little idea if my post is of any help, but anyway, today I built LP64 version of ssh client and found that, LP64 version of struct passwd does have pw_gecos member (so you need to set ac_cv_member_struct_passwd_pw_gecos=yes for LP64 build), but, the value of it is set to NULL, causing SEGV, at least on Android 8.0 device with uid = AID_SHELL (2000). So you need to fix the source like this.

diff -rup openssh-9.6p1/misc.c openssh-9.6p1-droid-p01/misc.c
--- openssh-9.6p1/misc.c        2023-12-18 23:59:50.000000000 +0900
+++ openssh-9.6p1-droid-p01/misc.c      2024-01-31 17:10:46.530066587 +0900
@@ -488,7 +488,7 @@ pwcopy(struct passwd *pw)
        copy->pw_name = xstrdup(pw->pw_name);
        copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd);
 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
-       copy->pw_gecos = xstrdup(pw->pw_gecos);
+       copy->pw_gecos = xstrdup(pw->pw_gecos == NULL ? "null" : pw->pw_gecos);
 #endif
        copy->pw_uid = pw->pw_uid;
        copy->pw_gid = pw->pw_gid;

 ---

OpenSSH has been configured with the following options:
                     User binaries: /system/usr/bin
                   System binaries: /system/usr/sbin
               Configuration files: /system/etc/ssh
                   Askpass program: /system/usr/libexec/ssh-askpass
                      Manual pages: /system/usr/man/manX
                          PID file: /data/local/tmp/var/run
  Privilege separation chroot path: /data/local/tmp/var/empty
            sshd default user PATH: /system/bin
                    Manpage format: doc
                       PAM support: no
                   OSF SIA support: no
                 KerberosV support: no
                   SELinux support: yes
                   libedit support: yes
                   libldns support: yes
  Solaris process contract support: no
           Solaris project support: no
         Solaris privilege support: no
       IP address in $DISPLAY hack: no
           Translate v4 in v6 hack: no
                  BSD Auth support: no
              Random number source: OpenSSL internal ONLY
             Privsep sandbox style: none
                   PKCS#11 support: yes
                  U2F/FIDO support: yes

              Host: aarch64-unknown-linux-android
          Compiler: /data/develop/android/android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang
    Compiler flags: --sysroot /data/develop/android/android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/ -O2 -w -I/data/develop/android/sysroot/usr/include -I/data/develop/android/android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot//usr/include -Wno-implicit-function-declaration -Wno-int-conversion -fPIE -I/data/develop/android/sysroot/selinux/usr/include -DHAVE_SETRESGID=1 -pipe -Wunknown-warning-option -Wno-error=format-truncation -Qunused-arguments -Wall -Wextra -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-parameter -Wno-unused-result -Wimplicit-fallthrough -Wmisleading-indentation -Wbitwise-instead-of-logical -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -ftrapv -fzero-call-used-regs=used -ftrivial-auto-var-init=zero -mretpoline -fno-builtin-memset -Dfd_mask=int  
Preprocessor flags: -I/data/develop/android/sysroot/usr/include  -DHAVE_ATTRIBUTE__SENTINEL__=1 -DBROKEN_SETRESGID  -I/system/usr/include -I/data/local/tmp/develop/sysroot/usr/include
      Linker flags: -L/data/develop/android/sysroot/usr/lib -L/data/local/tmp/develop/sysroot/usr/lib --sysroot /data/develop/android/android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/  -s -ffunction-sections -fdata-sections -Wl,--gc-sections -L/data/develop/android/sysroot/usr/lib -L/data/develop/android/android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot//lib -L/data/develop/android/sysroot/selinux/usr/lib -ldl -lcrypto -lssl -lpcre2  -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,retpolineplt -L/system/usr/lib 
         Libraries: -lldns  -lselinux
     +for channels: -lcrypto  -lz





Trouble Shooting

Due to the energy saving functions of Android, the wifi connection can be put into sleep mode too often, so that the ssh connection to the phone is very sluggish. To work around this problem, start a ping command in the background to use the WIfi connection continuously, e.g:

ping -i 0.2 192.168.1.1 >/dev/null & 


hostname resolution via DNS is not possible if the sshd was started via the Magisk service.sh script and the current user in the ssh session is NOT the root user. To work around this issue, either restart the sshd in an adb session or execute the commands that need hostname resolution via DNS in the ssh sessions as user root. The script

restart_ssh_daemon

can be used in an adb session to restart the sshd. 


To execute the customize script of the Magisk Module with "set -x" and write STDOUT and STDERR to the file /data/local/tmp/openssh_customize.log create the (probably empty) file /data/local/tmp/debug before installing the Magisk Module.


To execute the service script to start the sshd with "set -x" and write STDERR and STDLOG messages to the file /data/local/tmp/start_sshd.log create the file /data/local/tmp/debug before rebooting the phone.


 ---

History

12.05.2025 10.0p2.v1.0.0 
  initial release

20.06.2025 10.0p2.v1.1.0
  the privilege separation user is now "nobody" -> the sshd can be started by the root user

02.10.2025 10.0p2.v1.2.0
  relinked all binaries using the libraries from OpenSSL v3.5.4
  the directory /data/local/tmp/var/empty is now owned by root (the directory is not used if the sshd is started by the user shell)

