OpenSSH源码编译安装


一.     基础环境准备

操作系统:Ubuntu16.04Server

sudo apt-get install vim openssh-server

 便于后续上传源码以及调试。

看一下现在openssh的版本:

zjd@ubuntu:~$ ssh -V OpenSSH_7.2p2 Ubuntu-4ubuntu2.6, OpenSSL 1.0.2g  1 Mar 2016

 安装编译所需要的库:

zjd@ubuntu:~$ sudo apt-get install build-essential

 二.     源码下载

从https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/下载最新的openssh-7.9p1.tar.gz;
从http://www.zlib.net/下载最新的zlib-1.2.11.tar.gz;
https://www.openssl.org/source/下载最新的openssl-1.1.1a.tar.gz。
/home/zjd/下新建mySSH目录,然后将这三个压缩包上传上去后用tar分别解压:
zjd@ubuntu:~/mySSH$ tar -zxvf zlib-1.2.11.tar.gz

 。。。

zjd@ubuntu:~/mySSH$ ll total 10312 drwxrwxrwx 5 root root    4096 Dec 17 16:41 ./ drwxr-xr-x  4 root root    4096 Dec 17 16:27 ../ drwxr-xr-x  5 zjd  zjd    12288 Oct 18 18:06 openssh-7.9p1/
-rw-rw-r--  1 zjd  zjd  1565384 Dec 17 16:39 openssh-7.9p1.tar.gz drwxr-xr-x 19 zjd  zjd     4096 Nov 20 05:35 openssl-1.1.1a/
-rw-rw-r--  1 zjd  zjd  8350547 Dec 17 16:39 openssl-1.1.1a.tar.gz drwxr-xr-x 14 zjd  zjd     4096 Jan 15  2017 zlib-1.2.11/
-rw-rw-r--  1 zjd  zjd   607698 Dec 17 16:39 zlib-1.2.11.tar.gz

 三.     编译安装

1. zlib

进文件夹后直接配置编译安装:

zjd@ubuntu:~/mySSH/zlib-1.2.11$ ./configure --prefix=/usr/local zjd@ubuntu:~/mySSH/zlib-1.2.11$ make zjd@ubuntu:~/mySSH/zlib-1.2.11$ sudo make install

 2. openssl

注意要先卸载旧版本:

zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ sudo apt-get purge openssl

 删除旧配置文件:

zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ rm -rf /etc/ssl

 然后配置编译安装新版本:

zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ ./config  --prefix=/usr/local --openssldir=/usr/local/ssl zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ make zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ sudo make install zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ ./config shared --prefix=/usr/local --openssldir=/usr/local/ssl zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ make clean zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ make zjd@ubuntu: ~/mySSH/openssl-1.1.1a$ sudo make install

 其中:prefix 是安装目录,openssldir 是配置文件目录,另外建议安装两次,shared 作用是生成动态连接库。

最后,因为是非root用户安装,因此需要增加两条软连接:

zjd@ubuntu:~/mySSH/openssl-1.1.1a$ sudo ln -s /usr/local/lib/libssl.so.1.1 /usr/lib/libssl.so.1.1 zjd@ubuntu:~/mySSH/openssl-1.1.1a$ sudo ln -s /usr/local/lib/libcrypto.so.1.1 /usr/lib/libcrypto.so.1.1

 OK,现在看一下openssl的版本:

zjd@ubuntu:~/mySSH/openssl-1.1.1a$ openssl version OpenSSL 1.1.1a  20 Nov 2018

 3. openssh

zjd@ubuntu:~/mySSH/openssh-7.9p1$ ./configure -prefix=/usr/local -sysconfdir=/etc/ssh -with-ssl-dir=/usr/local/ssl zjd@ubuntu:~/mySSH/openssh-7.9p1$ make zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo make install

 安装完重启服务:

zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo systemctl restart sshd.service

 现在再看一下ssh的版本:

zjd@ubuntu:~/mySSH/openssh-7.9p1$ ssh -V OpenSSH_7.9p1, OpenSSL 1.1.1a  20 Nov 2018

 四.     修改openssh源码

当修改了openssh源码后,为了不影响系统已启动的ssh服务的运行,应该重新配置编译输出路径,然后停掉系统已启动的ssh服务,启动新编译的sshd。过程如下:

zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo vim session.c zjd@ubuntu:~/mySSH/openssh-7.9p1$ make clean zjd@ubuntu:~/mySSH/openssh-7.9p1$  ./configure -prefix=/usr/local/myssh -sysconfdir=/etc/ssh -with-ssl-dir=/usr/local/ssl zjd@ubuntu:~/mySSH/openssh-7.9p1$ make zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo make install zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo /etc/init.d/ssh stop zjd@ubuntu:~/mySSH/openssh-7.9p1$ sudo /usr/local/myssh/sbin/sshd

 再次继续修改时,最后两行停止和启动服务的操作就不用执行了。

如果重启了系统,则最后两步要重新执行一下。当然,也可以写个开机启动脚本,这样系统启动时就自动执行最后两行了,方法如下:

在/etc/init.d/目录下新建一个脚本文件startmyssh.sh,并赋予运行权限:

zjd@ubuntu:/etc/init.d$ sudo chmod 755 startmyssh.sh

 vim编辑脚本内容为:

#!/bin/bash
### BEGIN INIT INFO
# Provides: Zhang Jidong
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: sshd service
# Description: mysshd service
### END INIT INFO
sudo /etc/init.d/ssh stop sudo /usr/local/myssh/sbin/sshd exit 0

 注意前面的注释部分格式一定要一样,否则会有各种警告;

最后添加启动调用:

zjd@ubuntu:/etc/init.d$ sudo update-rc.d startmyssh.sh defaults 90

 好了,现在可以重启试试了!

五.     openssh日志

openssh的配置文件位于:

zjd@ubuntu:/etc/ssh$ sudo vim sshd_config

  

# Logging
SyslogFacility AUTH LogLevel INFO

 详细定义位于log.h,如下:

/* Supported syslog facilities and levels. */ typedef enum { SYSLOG_FACILITY_DAEMON, SYSLOG_FACILITY_USER, SYSLOG_FACILITY_AUTH, #ifdef LOG_AUTHPRIV
 SYSLOG_FACILITY_AUTHPRIV, #endif
 SYSLOG_FACILITY_LOCAL0, SYSLOG_FACILITY_LOCAL1, SYSLOG_FACILITY_LOCAL2, SYSLOG_FACILITY_LOCAL3, SYSLOG_FACILITY_LOCAL4, SYSLOG_FACILITY_LOCAL5, SYSLOG_FACILITY_LOCAL6, SYSLOG_FACILITY_LOCAL7, SYSLOG_FACILITY_NOT_SET = -1 } SyslogFacility; typedef enum { SYSLOG_LEVEL_QUIET, SYSLOG_LEVEL_FATAL, SYSLOG_LEVEL_ERROR, SYSLOG_LEVEL_INFO, SYSLOG_LEVEL_VERBOSE, SYSLOG_LEVEL_DEBUG1, SYSLOG_LEVEL_DEBUG2, SYSLOG_LEVEL_DEBUG3, SYSLOG_LEVEL_NOT_SET = -1 } LogLevel;

 SyslogFacility配置为AUTH,则日志会输出到/var/log/auth.log

六.     sftp日志

sftp是openssh根据功能需要启动的子进程,缺省是关闭了日志的。打开方法为:

 

sudo vim /etc/ssh/sshd_config

 在Subsystem所在行最后增加 -l DEBUG3,如下:

Subsystem   sftp    /usr/libexec/openssh/sftp-server -l DEBUG3

 将sftp的日志单独存放:

 

sudo vim /etc/rsyslog.conf

 最后面增加如下内容:

# Log sftp-server in a separate file
:programname, isequal, "sftp-server" /var/log/sftp.log

 现在就可以重启sshd服务和rsyslog服务来生效了:

sudo systemctl restart rsyslog.service
sudo systemctl restart sshd.service

 看:

zjd@ubuntu:/var/log$ ll -t total 1532
-rw-r-----  1 syslog adm    379366 Dec 20 04:58 syslog -rw-r-----  1 syslog adm     61409 Dec 20 04:53 auth.log -rw-r-----  1 syslog adm      6460 Dec 20 04:41 sftp.log drwxrwxr-x  7 root   syslog   4096 Dec 20 04:40 ./ drwxr-xr-x 12 root   root     4096 Dec 20 04:31 ../
-rw-r--r--  1 root   root   568865 Dec 20 04:25 dpkg.log -rw-rw-r--  1 root   utmp   292292 Dec 20 04:22 lastlog -rw-rw-r--  1 root   utmp     5376 Dec 20 04:22 wtmp -rw-r-----  1 syslog adm    348026 Dec 20 04:22 kern.log

 ……

建议设置logrotate避免日志过大。方法是sudo vim创建/etc/logrotate.d/sftp文件,输入下面内容并保存:

/var/log/sftp.log { postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true endscript }

 如果此时通过FileZilla客户端访问openssh-server,查看文件列表以及上传下载等操作,可以通过日志发现这些操作的实现都在sftp-server.c中。

 七.     限制sftp用户只能访问指定目录

 添加用户test1:

 

zjd@ubuntu:/home$ sudo useradd test1

 为test1设置密码:

 

zjd@ubuntu:/home$ sudo passwd test1

 编辑

sudo vim /etc/ssh/sshd_config

 将已有的Subsystem sftp /usr/lib/openssh/sftp-server -l DEBUG3改为:

 

Subsystem sftp internal-sftp -l DEBUG3

 并在最后为test1增加如下配置:

 

Match User test1 ChrootDirectory /home/test1 X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp -l DEBUG3

 创建好目录:

 

zjd@ubuntu:/home# sudo mkdir test1

 权限设置:

 

zjd@ubuntu:/home$ sudo chown root:root /home/test1 zjd@ubuntu:/home$ sudo chmod 755 /home/test1 zjd@ubuntu:/home$ sudo usermod test1 -s /sbin/nologin

 现在重启sshd服务,可以发现已经是只能登录到/home/test1目录中了。但此时没有写权限,那就继续如下配置,给test1配置一个可以读写的data文件夹:

 

zjd@ubuntu:/home/test1# sudo mkdir data
zjd@ubuntu:/home/test1# sudo chown test1:test1 /home/test1/data/
zjd@ubuntu:/home/test1# sudo chmod 755 /home/test1/data/

 好了,现在用户通过sftp登录后,就能看到一个data文件夹,并且在这个data文件夹里面可以进行读写操作了。

 此时前面加的-l DEBUG3参加(打印sftp.log)无效了,需要再进行如下配置:

 /home/test1下新建dev文件夹:

 

zjd@ubuntu:/home/test1# sudo mkdir dev

 编辑sudo vim /etc/rsyslog.conf,最后面新增:

 

# Create an additional socket for some of the sshd chrooted users.
$AddUnixListenSocket /home/test1/dev/log # Log internal-sftp in a separate file
:programname, isequal, "sftp" /var/log/sftp.log

 (如果增加多个用户,只需重复增加AddUnixListenSocket命令即可。)

 编辑

root@ubuntu:/home# vim /etc/selinux/config

 新增:

 

SELINUX=disabled

 重启一下日志服务:

 

zjd@ubuntu:/home/test1# sudo systemctl restart rsyslog.service

 好了,现在重启系统吧!

 此时sftp用户登录后看到的是两个文件夹data和dev,如果自动进入data文件夹,则体验更好。此时就需要修改sftp-server.c,在函数process_realpath中增加如下

if (strlen(path) == 1 && !strcmp(path, "."))部分的内容

 

static void process_realpath(u_int32_t id) { char resolvedname[PATH_MAX]; char *path; int r; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (path[0] == '\0') { free(path); path = xstrdup("."); } debug3("request %u: realpath", id); verbose("realpath \"%s\"", path); if (strlen(path) == 1 && !strcmp(path, ".")) { logit("======== Change path from '.' to '/data/.'"); free(path); path = xstrdup("/data/."); } if (realpath(path, resolvedname) == NULL) { send_status(id, errno_to_portable(errno)); } else { Stat s; attrib_clear(&s.attrib); s.name = s.long_name = resolvedname; send_names(id, 1, &s); } free(path); } 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM