1、爲何?html
在中小型企業,公司不一樣運維人員基本都是以root 帳戶進行服務器的登錄管理,缺乏了帳戶權限審計制度。不出問題還好,出了問題,就很難找出源頭。linux
這裏介紹下,如何利用編譯bash 使不一樣的客戶端在使用root 登錄服務器使,記錄各自的操做,而且能夠在結合ELK 日誌分析系統,來收集登錄操做日誌算法
2、環境shell
服務器:centos 6.五、Development tools、使用密鑰認證,SElinux 關閉。swift
客戶端:生成密鑰對,用於登陸服務器 (2臺)vim
3、搭建部署 (服務器操做 192.168.30.72)centos
3.1 下載編譯bashbash
[root@open1 ~]# wget http://ftp.gnu.org/gnu/bash/bash-4.1.tar.gz [root@open1 ~]# tar xvf bash-4.1.tar.gz [root@open1 ~]# cd bash-4.1
3.2 先修改下 config-top.c文件,大概94行、104行,因爲c 語言中 註釋是/**/ ,因此不要刪除錯了。修改以下:服務器
[root@open1 bash-4.1]# vim config-top.c #define SSH_SOURCE_BASHRC #define SYSLOG_HISTORY
3.3 修改下bashhist.c 文件,讓終端上的命令記錄到系統messages 中,而且以指定的格式。並傳入得到的變量。修改後的內容以下:運維
[root@open1 bash-4.1]# vim bashhist.c #... 省略部分段落 void bash_syslog_history (line) const char *line; { char trunc[SYSLOG_MAXLEN]; const char *p; p = getenv("NAME_OF_KEY"); if (strlen(line) < SYSLOG_MAXLEN) syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d PPID=%d SID=%d User=%s USER=%s CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, p, line); else { strncpy (trunc, line, SYSLOG_MAXLEN); trunc[SYSLOG_MAXLEN - 1] = ' '; syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d PPID=%d SID=%d User=%s USER=%s CMD=%s", getpid(), getppid(), getsid(getpid()), current_user.user_name, p, trunc); } }
3.4 配置安裝路徑,編譯安裝,編譯到/usr/local/目錄下。
[root@open1 bash-4.1]# ./configure --prefix=/usr/local/bash_new [root@open1 bash-4.1]# make && make install ... if test "bash" = "gettext-tools"; then \ /bin/sh /root/bash-4.1/./support/mkinstalldirs /usr/local/bash_new/share/gettext/po; \ for file in Makefile.in.in remove-potcdate.sin quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot Makevars.template; do \ /usr/bin/install -c -m 644 ./$file \ /usr/local/bash_new/share/gettext/po/$file; \ done; \ for file in Makevars; do \ rm -f /usr/local/bash_new/share/gettext/po/$file; \ done; \ else \ : ; \ fi make[1]: Leaving directory `/root/bash-4.1/po'
編譯完成後,將新的bash 追加到 /etc/shells 中,並修改root用戶的登錄shell 環境爲新編譯的shell。以下
[root@open1 bash-4.1]# echo "/usr/local/bash_new/bin/bash" >> /etc/shells [root@open1 bash-4.1]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash /usr/local/bash_new/bin/bash
[root@open1 bash-4.1]# vim /etc/passwd root:x:0:0:root:/root:/usr/local/bash_new/bin/bash
註銷當前root用戶,從新登錄後,查看/var/log/messages,以下就能夠看到記錄了操做命令
4、SSH客戶端生成密鑰部分
4.1 在client1上(192.168.30.99)操做,用戶zhangsan
[root@rsyslog ~]# ssh-keygen -t rsa -C "root@zhangsan" Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: c8:bd:5d:3b:a5:d9:6d:09:b6:5f:db:55:1d:43:96:3d root@zhangsan The key's randomart image is: +--[ RSA 2048]----+ | oo| | oE.| | o.| | . o +| | o S .o. o| | o ..*o.o| | . . =...=| | ...=| | o.| +-----------------+
-t 加密算法
-C 註釋 (加上這個也是爲了最後進行對服務器訪問人員進行辨別的一個關鍵點)
將公鑰上傳到服務器上的.ssh/authorized_keys 文件中。ssh-copy-id 命令會自動在服務器上建立.ssh/authorized_keys文件,即便該目錄不存在,並自動賦予600權限。
[root@rsyslog ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.30.72 root@192.168.30.72's password: Now try logging into the machine, with "ssh 'root@192.168.30.72'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting.
4.3 client 2(192.168.30.71) 上一樣的操做,用戶lisi
[root@swift3 ~]# ssh-keygen -t rsa -C "root@lisi" Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 8f:56:66:91:0c:6e:86:3b:90:19:42:9c:ab:9e:00:f6 root@lisi The key's randomart image is: +--[ RSA 2048]----+ | oo.. . | | o. + o o . | | .+ . + + | |... . + . | |o.. o S + | |o E . * | |o . o . | | o . | | | +-----------------+
上傳公鑰到服務器上
[root@swift3 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.30.72 The authenticity of host '192.168.30.72 (192.168.30.72)' can't be established. RSA key fingerprint is 8f:a7:1b:8d:e4:92:ad:ae:ea:1b:fb:67:0b:0b:7c:ac. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.30.72' (RSA) to the list of known hosts. root@192.168.30.72's password: Now try logging into the machine, with "ssh 'root@192.168.30.72'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting.
4.4 如今去服務器上驗證下該文件。
[root@open1 ~]# cat ~/.ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6fM+bpWEP3luauvOjmTB55ugUzVVMesmHCw4RNZ/C2e+KGXAYuxuAmEBbMcXQQj7OTAqVCQ0PWja58wReyZ7etiUGAtvoSBmSBpTPXteBMl40kDn4GdmXQ9UT/jnQ9gSZUQYJLMLJGWJks9S4xUI2cZ7oIytclrsUnKuOA1U6+luIJwJu9z7ya5OXh5FmmJQFnYtAEIhrLt4S8Ru5S00c0jiQCRk3RFlHYNc0IR02MXMH7d9bq7l04heAcT/y1EBS3EwINX8r0y6OridjJPCwxnm1sSfMKvLAbq/B+ufDjEOp7Y2SatL3qXaiP7NxdnhoJ4+Xar0zCoYi2A9oRGgUQ== root@zhangsan ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAupGSgXOWpQfzOVkHXYqN2BjMiAyaFRdKs6Wam3xGpMYRjZbIFX14kNR4CbrQtbUK8YonZPYdXG589blFmqF17sUPCNEqZEjCNer+yzDu+hYg/jAn4dCVtTBqUtBsTYUHSHIR0srruJ9keHNgU9aDRok8nulMUi/9Ej0NJZsBQ2npVNCf0YHgAd/ON5VsBYVLPvAT/cG3MuCjg5mgtU59qgAHyLKxkfpVc0/TRZ4eamX/1V0dsCxx9oYDbpn4YKLBAOaAS4kF6qEdrwRh0ssyWtWOo/CdyfLXKgwdbPtPfWZ63SM7wY7bAtcdxxu/QDkYVP+4oDfAtMxXZlY2bT5qMQ== root@lisi
如今上面兩個客戶端已經能夠免密鑰登錄了,如今去服務器上配置,並建立腳本。
5、配置服務器
5.1 在log目錄下建立一個 keys 文件,用於登錄時存進去公鑰,以後對其進行取出判斷的
[root@open1 ~]# touch /var/log/keys
建立檢測腳本,內容以下:
[root@open1 ~]# cat /etc/CheckUser.sh #!/bin/bash #conding:utf-8 pid=$PPID #在本身home目錄獲得全部的key,若是/var/log/keys 沒有的時候,添加進去 while read line do grep "$line" /var/log/keys >/dev/null || echo "$line" >> /var/log/keys done < $HOME/.ssh/authorized_keys #獲得每一個key的指紋 cat /var/log/keys | while read LINE do NAME=$(echo $LINE | awk '{print $3}') echo $LINE >/tmp/keys.log.$pid KEY=$(ssh-keygen -l -f /tmp/keys.log.$pid | awk '{print $2}') grep "$KEY $NAME" /var/log/ssh_key_fing >/dev/null || echo "$KEY $NAME" >> /var/log/ssh_key_fing done #若是是root用戶,secure文件裏面是經過PPID號驗證指紋 if [ $UID == 0 ] then ppid=$PPID else #若是不是root用戶,驗證指紋的是另一個進程號 ppid=`/bin/ps -ef | grep $PPID |grep 'sshd:' |awk '{print $3}'` fi #獲得RSA_KEY和NAME_OF_KEY,用來bash4.1獲得歷史記錄 RSA_KEY=`/bin/egrep 'Found matching RSA key' /var/log/secure | /bin/egrep "$ppid" | /bin/awk '{print $NF}' | tail -1` if [ -n "$RSA_KEY" ];then NAME_OF_KEY=`/bin/egrep "$RSA_KEY" /var/log/ssh_key_fing | /bin/awk '{print $NF}'` fi #把NAME_OF_KEY設置爲只讀 readonly NAME_OF_KEY export NAME_OF_KEY /bin/rm /tmp/keys.log.$pid
5.2 配置 profile,在文件末尾添加一行內容,以下:
[root@open1 ~]# echo "test -f /etc/CheckUser.sh && . /etc/CheckUser.sh" >> /etc/profile
在/etc/bashrc 末尾添加下面內容:
[root@open1 ~]# tail -1f /etc/bashrc test -z "$BASH_EXECUTION_STRING" || { test -f /etc/CheckUser.sh && . /etc/CheckUser.sh; logger -t -bash -s "HISTORY $SSH_CLIENT USER=$NAME_OF_KEY CMD=$BASH_EXECUTION_STRING " >/dev/null 2>&1;}
5.3 修改sshd 配置文件,開啓debug 模式,並重啓sshd 服務
[root@open1 ~]# sed -i 's/#LogLevel INFO/LogLevel DEBUG/g' /etc/ssh/sshd_config [root@open1 ~]# service sshd restart Stopping sshd: [ OK ] Starting sshd: [ OK ]
6、驗證
6.1 在client1 上進行登錄,並刪除個文件試下(zhangsan)
6.2 在client2 上進行登錄,也刪除個文件,並執行個重啓服務的命令(lisi)
6.3 去服務器上查看下 messages 日誌,內容以下
經過上圖,能夠看出,不通用戶的客戶端經過公鑰登錄的方式,分辨出了誰操做了什麼,何時操做的。
(注:上圖第4段 swift1 是這臺服務器的主機名,因爲我只是運行了hostname 命令修改主機名,並無修改networks,因此內核裏仍是以前的名字:swift1。)
7、結束
經過這種方式,極大的解決了多root 用戶登錄操做,沒法審計的問題。而且能夠結合日誌轉發,將系統日誌轉發到其它服務器,即便主機被黑了,也能具體的審查登錄時間以及作了哪些操做。
若有轉載請註明出處,謝謝。