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