Linux 系統安全與優化配置

http://netkiller.github.io/journal/security.html

Mr. Neo Chen (陳景峯), netkiller, BG7NYT


中國廣東省深圳市龍華新區民治街道溪山美地
518131
+86 13113668890


版權聲明

轉載請與作者聯繫,轉載時請務必標明文章原始出處和作者信息及本聲明。

文檔出處:
http://netkiller.github.io
http://netkiller.sourceforge.net

微信掃瞄二維碼進入 Netkiller 微信訂閲號

QQ群:128659835 請註明“讀者”

摘要

Linux 系統安全問題

2013-07-25 首發

2016-11-16 更新


目錄

1. Openssh 安全配置

這節主要講與SSH有關的安全配置

1.1. 禁止root用戶登錄

只允許普通用戶登陸,然後通過su命令切換到root用過。後面還會將怎樣限制su命令

			
PermitRootLogin no
			
			

1.2. 限制SSH驗證重試次數

超過3次socket連接會斷開,效果不明顯,有一點點用。

			
MaxAuthTries 3
			
			

1.3. 禁止證書登陸

證書登陸非常安全,但是很有可能正常用戶在你不知道情況下,給你安裝了一個證書,他隨時都可能進入你的系統

任何一個有權限的用戶都能很方便的植入一個證書到 .ssh/authorized_keys 檔案中

			
PubkeyAuthentication no
AuthorizedKeysFile /dev/null
			
			

1.4. 使用證書替代密碼認證

是不是自相矛盾? 這個跟上面講的正好相反,這裡只允許使用key檔案登陸。

			
PasswordAuthentication no
			
			

這種方式比起密碼要安全的多,唯一要注意的地方就是證書被拷貝 ,建議你給證書加上 passphrase。

證書的 passphrase 是可以通過openssl工具將其剝離的,SSH證書我沒有試過,但是原理都差不多。

1.5. 圖形窗口客戶端記憶密碼的問題

當你使用XShell, Xftp, WinSCP, SecureCRT, SecureFX ......等等軟件登錄時,該軟件都提供記住密碼的功能,使你下次再登陸的時候無須輸入密碼就可以進入系統。這樣做的確非常方便,

但是你是否想過你的電腦一旦丟失或者被其他人進入,那有多麼危險。我之前每天背着筆記型電腦上班,上面安裝着XShell並且密碼全部記憶在裡面。這使我意識到一點電腦丟失,有多麼可怕。

禁止SSH客戶端記住密碼,你不要要求別人那麼做。你也無法控制,最終我找到了一種解決方案。

			
ChallengeResponseAuthentication yes
			
			

每次登陸都回提示你輸入密碼。密碼保存也無效。

1.6. 關閉 GSSAPI

			
GSSAPIAuthentication no
#GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
			
			

1.7. 禁止SSH連接埠映射

禁止使用SSH映射Socks5翻牆等等

			
AllowTcpForwarding no
			
			

1.8. IP地址限制

只允許通過192.168.2.1,192.168.2.2 訪問本機

# vim /etc/hosts.allow
sshd:192.168.2.1,192.168.2.2

			

禁止所有人訪問本機

# vim /etc/hosts.deny
sshd:ALL
			

上面使白名單策略,你也可以採用黑名單策略。

1.9. 禁止SSH密碼窮舉

駭客常常使用駭客字典窮舉你的SSH密碼,使用下面腳本可以封殺頻繁連結的IP地址

			
#!/bin/bash
########################################
# Homepage: http://netkiller.github.io
# Author: neo <netkiller@msn.com>
########################################
PIPE=/var/tmp/pipe
pidfile=/var/tmp/$0.pid
BLACKLIST=/var/tmp/black.lst
WHITELIST=/var/tmp/white.lst

LOGFILE=/var/log/secure
DAY=5
########################################

if [ -z "$( egrep "CentOS|7." /etc/centos-release)" ]; then
	echo 'Only for CentOS 7.x'
	exit
fi

if [ -f $BLACKLIST ]; then
	find $BLACKLIST -type f -mtime +${DAY} -delete
fi

if [ ! -f ${BLACKLIST} ]; then
    touch ${BLACKLIST}
fi

if [ ! -f ${WHITELIST} ]; then
    touch ${WHITELIST}
fi

for ipaddr in $(grep rhost ${LOGFILE} | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort | uniq -c | sort -r -n | head -n 10| awk '{print $2}')
do

    if [ $(grep -c $ipaddr ${WHITELIST}) -gt 0 ]; then
		continue
    fi

    if [ $(grep -c $ipaddr ${BLACKLIST}) -eq 0 ] ; then
		echo $ipaddr >> ${BLACKLIST}
        iptables -I INPUT -p tcp --dport 22 -s $ipaddr -j DROP
        #iptables -I INPUT -s $ipaddr -j DROP
    fi
done			
						
			

2. Shell 安全

2.1. .history 檔案

SA的操作記錄問題

通過~/.bash_history檔案記錄系統管理員的操作記錄,定製.bash_history格式

HISTSIZE=1000
HISTFILESIZE=2000
HISTTIMEFORMAT="%Y-%m-%d-%H:%M:%S "
export HISTTIMEFORMAT
			

看看實際效果

$ history | head
    1  2012-02-27-09:10:45 do-release-upgrade
    2  2012-02-27-09:10:45 vim /etc/network/interfaces
    3  2012-02-27-09:10:45 vi /etc/network/interfaces
    4  2012-02-27-09:10:45 ping www.163.com
			

2.2. sudo 安全問題

/etc/sudoers

			
Cmnd_Alias WEBMASTER = /srv/nginx/sbin/nginx, /srv/php/sbin/php-fpm, !/srv/mysql/bin/*
www localhost = NETWORKING, SERVICES, DELEGATING, PROCESSES, WEBMASTER

Cmnd_Alias Database = /usr/bin/mysqldump, /srv/mysql/bin/mysql, /u01/oracle/10.x.x/bin/sqlplus
mysql localhost = NETWORKING, SERVICES, DELEGATING, PROCESSES, WEBMASTER, Database
			
			

使用www用戶測試登錄,無誤後修改SSH配置檔案,禁止root登錄。

			
vim /etc/ssh/sshd_config
PermitRootLogin no
			
			

然後在測試從www sudo 執行命令, 可能成功啟動nginx 與 php-fpm

2.3. 臨時檔案安全

臨時檔案不應該有執行權限

/tmp

/dev/sda3 /tmp ext4 nosuid,noexec,nodev,rw 0 0
			

同時使用符號連接將/var/tmp 指向 /tmp

/dev/shm

none /dev/shm tmpfs defaults,nosuid,noexec,rw 0 0
			

2.4. 執行權限

以資料庫為例,從安全形度考慮我們需要如下更改

chown mysql:mysql /usr/bin/mysql*
chmod 700 /usr/bin/mysql*
			

mysql用戶是DBA專用用戶, 其他用戶將不能執行mysql等命令。

3. 防火牆

開啟防火牆

lokkit --enabled
		

3.1. 策略

預設INPUT,FORWARD,OUTPUT 三個都是ACCEPT

			
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
			
			

從安全的角度出發,INPUT,FORWARD,OUTPUT 三個都是DROP最安全,但配置的時候會給你帶來非常多的不可預料的麻煩。

			
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
			
			

折中的方案,也是打多少硬件防火牆廠商改採用的方案,他們都是採用INPUT預設禁用所有,OUTPUT預設允許所有,你只要關注INPUT規則即可。

			
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
			
			

3.2. 防止成為跳板機

跳板機就是用戶首先登陸任意一台伺服器後,由該伺服器在登陸另外一台伺服器。

封鎖22等連接埠,避免相互跳轉

iptables -A OUTPUT -p tcp -m multiport --dports 22,21,873 -j REJECT
/etc/init.d/iptables save
iptables -L -n
			

web 伺服器禁止使用ssh,作為跳板機

用戶將不能使用ssh命令登陸到其他電腦

3.3. 連接埠安全

有一種情況,例如你的伺服器被植入了木馬,木馬將開啟一個Socket連接埠給遠程駭客接入進來,通常會啟動一個類似telnet伺服器,怎樣防止未經允許的程序監聽一個連接埠呢?

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT  
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
-A INPUT -m state --state INVALID,NEW -j DROP
			

用法

  1. systemctl stop iptables

  2. 啟動 httpd / nginx

  3. systemctl start iptables

注意必須按照上面的步驟,如果你試圖如下嘗試將失敗

  1. systemctl start iptables

  2. 啟動 httpd / nginx

80連接埠將無法對外提供服務,因為當 -A INPUT -m state --state INVALID,NEW -j DROP 運行以後,任何試圖監聽連接埠的程序將被拒絶。

3.4. 封鎖特定字元串

下面的例子是拒絶爬蟲

# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Spider" -j DROP
# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Baidu" -j DROP
# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Robat" -j DROP
			

4. Linux 系統資源調配

4.1. /etc/security/limits.conf

很多資料上是這麼寫的

* soft nofile 65535
* hard nofile 65535
 			

這樣做是偷懶,會帶來很多問題,如果你的伺服器被攻擊,由於你的設置,系統將耗光你的資源,直到沒有任何響應為止,你可能鍵盤輸入都成問題,你不得不重啟伺服器,但你會發現重啟只能維持短暫幾分鐘,又會陷入無響應狀態。

			
nobody soft nofile 4096
nobody hard nofile 8192
			
			

為什麼會設置為nobody用戶呢?因為root用戶啟動系統後web 伺服器會使用nobody用戶創建子進程,socket連接實際上是nobody用戶在處理。root 僅僅是守護父進程。

mysql soft nofile 2048
mysql hard nofile 2048
			

針對 mysql 做限制

提示

關於 nofile 即打開檔案數,這個跟socket有非常緊密的關係,在linux系統中任何設備都被看做是一個檔案(字元設備),你連接一個滑鼠,鍵盤,攝像頭,硬碟等等都被看作打開一個設備檔案,所以預設1024是遠遠不夠的。

4.2. 關閉寫磁碟I/O功能

對於某些檔案沒必要記錄檔案的訪問時間,由其是在高並發的IO密集操作的環境下,通過兩個參數可以實現noatime,nodiratime減少不必要的系統IO資源。

編輯/etc/fstab 添加 noatime,nodiratime 參數

/dev/sdb1    /www          ext4    noatime,nodiratime        0 0
			

5. PAM 插件認證加固配置

配置檔案

ls  /etc/pam.d/
chfn         crond                login    passwd            remote    runuser-l          smtp          ssh-keycat  sudo-i       system-auth-ac
chsh         fingerprint-auth     newrole  password-auth     run_init  smartcard-auth     smtp.postfix  su          su-l
config-util  fingerprint-auth-ac  other    password-auth-ac  runuser   smartcard-auth-ac  sshd          sudo        system-auth
		

認證插件

ls /lib64/security/
		

5.1. pam_tally2.so

此模組的功能是,登陸錯誤輸入密碼3次,5分鐘後自動解禁,在未解禁期間輸入正確密碼也無法登陸。

在配置檔案 /etc/pam.d/sshd 頂端加入

auth required pam_tally2.so deny=3 onerr=fail unlock_time=300
			

查看失敗次數

# pam_tally2
Login           Failures Latest failure     From
root               14    07/12/13 15:44:37  192.168.6.2
neo                 8    07/12/13 15:45:36  192.168.6.2
			

重置計數器

# pam_tally2 -r -u root
Login           Failures Latest failure     From
root               14    07/12/13 15:44:37  192.168.6.2

# pam_tally2 -r -u neo
Login           Failures Latest failure     From
neo                 8    07/12/13 15:45:36  192.168.6.2
			

pam_tally2 計數器日誌保存在 /var/log/tallylog 注意,這是二進制格式的檔案

例 1. /etc/pam.d/sshd - pam_tally2.so
# cat  /etc/pam.d/sshd
#%PAM-1.0
auth required pam_tally2.so deny=3 onerr=fail unlock_time=300

auth	   required	pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    optional     pam_keyinit.so force revoke
session    include      password-auth
				

以上配置root用戶不受限制, 如果需要限制root用戶,參考下面

auth required pam_tally2.so deny=3 unlock_time=5 even_deny_root root_unlock_time=1800
			

5.2. pam_listfile.so

用戶登陸限制

將下面一行添加到 /etc/pam.d/sshd 中,這裡採用白名單方式,你也可以採用黑名單方式

auth       required     pam_listfile.so item=user sense=allow file=/etc/ssh/whitelist onerr=fail
			

將允許登陸的用戶添加到 /etc/ssh/whitelist,除此之外的用戶將不能通過ssh登陸到你的系統

# cat /etc/ssh/whitelist
neo
www
			
例 2. /etc/pam.d/sshd - pam_listfile.so
# cat /etc/pam.d/sshd
#%PAM-1.0
auth       required     pam_listfile.so item=user sense=allow file=/etc/ssh/whitelist onerr=fail
auth       required     pam_tally2.so deny=3 onerr=fail unlock_time=300

auth	   required	pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    optional     pam_keyinit.so force revoke
session    include      password-auth
				

sense=allow 白名單方式, sense=deny 黑名單方式

auth       required     pam_listfile.so item=user sense=deny file=/etc/ssh/blacklist onerr=fail
			

更多細節請查看手冊 $ man pam_listfile

5.3. pam_access.so

編輯 /etc/pam.d/sshd 檔案,加入下面一行

account required pam_access.so
			

保存後重啟sshd進程

編輯 /etc/security/access.conf 檔案

			
cat >>  /etc/security/access.conf << EOF

- : root : ALL EXCEPT 192.168.6.1
EOF
			
			

只能通過 192.168.6.1 登陸, 添加多個IP地址

- : root : ALL EXCEPT 192.168.6.1 192.168.6.2
			

測試是否生效

5.4. pam_wheel.so

限制普通用戶通過su命令提升權限至root. 只有屬於wheel組的用戶允許通過su切換到root用戶

編輯 /etc/pam.d/su 檔案,去掉下面的註釋

auth		required	pam_wheel.so use_uid
			

修改用戶組別,添加到wheel組

# usermod -G wheel www

# id www
uid=501(www) gid=501(www) groups=501(www),10(wheel)
			

沒有加入到wheel組的用戶使用su時會提示密碼不正確。

$ su - root
Password:
su: incorrect password