TShopping

 找回密碼
 註冊
搜索
查看: 1855|回復: 0
打印 上一主題 下一主題

[CentOS] SELinux 連線端口問題分析解決

[複製鏈接]
跳轉到指定樓層
1#
發表於 2020-8-24 23:31:15 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
 
Push to Facebook
CentOS 5.x 之後,SELinux 已經是個非常完備的核心模塊了,尤其是CentOS 提供了很多管理SELinux 的指令與機制,因此在整理架構上面是單純且容易操作管理的,所以在沒有自行開發網絡服務軟件以及使用其他第三方協力軟件的情況下,也就是全部使用CentOS 官方提供的軟件來使用我們服務器的情況下,建議不要關閉SELinux

#什麼是SELinux
Security Enhanced Linux 的縮寫SELinux,字面意思是安全強化的LInux。至於強化的是哪個部分?下面來了解下

#當初設計的目標:避免資源的誤用
SELinux 是由美國國家安全局(NSA)開發的,需求來源於內部員工資源誤用導致系統出現問題;

資源誤用:將一個/var/www/html/目錄權限設置成777,那麼當啟動www服務器軟件,就意味著這個軟件觸發的進程擁有對該目錄寫入的權限,只要通過該進程服務器對目錄大量寫入,就會導致系統硬盤資源被爆破

SELinux 是在進行進程、文件等西部權限設置依據的一個核心模塊,由於啟動網絡服務的也是進程,因此剛好也能夠控製網絡服務是否能存取系統資源的一道關卡

在講解SELinux 之前,先回顧一下之前講到的:系統文件權限與用戶之間的關係

#傳統的文件權限與賬戶關係:自主式訪問控制DAC
第13 章中講到:系統賬戶主要分為系統管理員(root)與一般用戶,他們能否使用系統上的文件資源與rwx 權限設置有關。(各種權限設置對root 無效)。當某個進程想要對文件進行存取時,系統會根據該進程的擁有者、群組,並比對文件的權限,若通過權限檢查,就可以存取該文件

這種存取文件的方式被稱為自主式訪問控制Discretionary Access Controller簡稱DAC,基本上就是依據進程的擁有者與文件資源的rwx權限來決定有無存取的能力。DAC有如下困擾:

root 具有最高的權限:只要取得屬於root 的進程,那麼就很危險
使用者可以取得進程來變更文件資源的訪問權限:如果將某個目錄權限不小心設置為777,由於對任何人的權限會變成rwx,因此該目錄就會被任何人所任意存取
#以政策規則規定特定進程讀取特定文件:委任式訪問控制MAC
為了避免DAC 的困擾,SELinux 導入了委任式訪問控制Mandatory Access Control 簡稱MAC

MAC可以針對特定的進程與特定的文件資源來進行權限的控制。即使你是root,那麼在使用不同的進程時,你所能取得的權限並不一定是root,而需要看當時該進程的設置。如此一來針對控制的「主體」變成了「進程」而不是使用者,但是真個系統進程很多、文件也很多,一項一項控制太麻煩,所以SELinux也提供一些預設的政策Policy,並在該政策內提供多個規則rule,讓你可以選擇是否啟用該控制規則

在該種模式下,進程能夠活動的空變小了。比如:www服務器軟件達成進程為httpd這個程序,默認情況下, httpd僅能在/var/www目錄下存取文件,如果httpd進程要去其他目錄存儲數據時,除了規則設置要開放外,目標目錄也要設置成httpd可讀取的模式type才行,限制非常多,所以,即使httpd這個進程被黑客取得了控制權限,它也無權限瀏覽其他的目錄文件

簡單說,針對Apache 這個www 網絡服務使用DAC 或MAC 的結果來說,兩者的關係可用下圖來說明



圓環表示畫地為牢,DAC 模式下,由於是root,牢房對root 無效。在MAC 下,牢房就生效了

#SELinux 的運作模式
強調:SELinux是通過MAC方式來管控進程,進程是主體,而目標則是該進程能否讀取的文件資源。

主體Subject:可以看成就是進程

目標Object:目標資源,一般就是文件系統

政策Policy:會根據某些服務來製定基本的存取安全性政策,政策內還會有詳細的規則rule 來指定不同的服務開放某些資源的存取。在目前的CentOS 7.x 裡面僅提供3 個主要的政策:

targeted:針對網絡服務限制較多,針對本機限制較少,是預設的政策
minimum:由target 修正而來,僅針對選擇的進程來保護
mls:完整的SELinux 限制,限制方面較嚴格
安全性本文security context

主體是否能存取目標除了政策指定之外,主體與目標的安全性本文必須一致才能夠順利存取

security context 類似文件系統的rwx,如果設置錯誤,你的某些服務(主體進程)就無法存取文件系統(目標資源),就會出現權限不符對的錯誤信息了

由於SELinux 重點在保護進程讀取文件系統的權限,上述說明的示意圖如下:



傳統的進程與文件的rwx方式,在這中間增加了SELinux月安全性本文規則,通過了這些規則之後,才和傳統的進程與文件的rwx方式一致。

筆者理解為是通過攔截器的方式,出台了SELinux ,前面通過SElinux 攔截細化權限,符合要求的再去到傳統的方式,這樣一來就對傳統的加強了

#安全性本文Security Context
CentOS 7.x 的target 政策提供了非常多的規則,只需要如何開啟關閉某項規則即可。

安全性本文則非常麻煩,可能需要自行配置它,比如你常常設置文件的rwx 權限,那麼這個安全性本文就類似,可以看成是SELinux 中的rwx

安全性本文存在於主體進程中與目標文件資源中,物理位置是放在文件的inode 中,因此主體進程想要讀取目標文件資源時,同樣需要讀取inode,這就可以對比安全性本文一級rwx 等權限是否正確了。

觀察安全性本文可使用ls -Z,但是前提是需要啟動SELinux才行,下個小節會介紹如何啟動SELinux,這裡先介紹知識點

  1. [root@study ~]# ls -Z
  2. -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 accountadd.sh
  3. -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 accountadd.txt
  4. -rwxr--r--+ root root unconfined_u:object_r:admin_home_t:s0 acl_test1
  5. -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 addaccount2.sh
  6. -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
  7. -rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg
  8. # 上述字段很长的那一栏就是安全性本文了
複製代碼

   
安全性本文主要用冒號分割為三個字段,含義如下:

identify:身份

相當於賬戶方面的身份識別,常見有幾下幾種類型

unconfined_u:不受限的用戶

該文件來自不受限的進程所產生的,一般來說,可以使用可登錄賬號來取得bash,預設的bash 環境是不受SELinux 管制的,因為bash 並不是什麼特別的網絡服務,因此在該bash 進程所產生的文件,其身份識別大多就是該類型了

system_u:系統用戶

基本上,如果是系統會軟件本身所提供的文件,大多就是該類型,如果是用戶通過bash 自己建立的文件,大多則是不受限的unconfined_u 身份,如果是網絡服務所產生的文件,或則是系統服務運行過程中所產生的文件,則大部分是system_u

role:角色

通過該字段,可以知道這個資料是屬於進程、文件資源還是代表使用者,一般的角色有:

object_r:代表的是文件或目錄等文件資源
system_r:代表的是進程,不過一般使用者也會被指定為system_r
type:類型,最重要

在預設的targeted 政策中, identify 與role 字段基本上是不重要的,而type 是最重要的,基本上,一個主體進程能不能讀取到這個文件資源,與類型字段有關,而類型字段在文件與進程的定義不相同:

type:在文件資源(object)上面稱為類型(type)
domain:在主體進程(subject)則稱為領域(domain)
domain 需要與type 搭配,則該進程才能夠順利的讀取文件資源

#進程與文件SELinux type 字段的相關性
通過身份識別與角色字段的定義,我們可以大概某個進程所代表的意義

# 观察下系统 进程的 SELinux 相关信息
  1. # 观察下系统 进程的 SELinux 相关信息
  2. [root@study ~]# ps -eZ
  3. LABEL                             PID TTY          TIME CMD
  4. system_u:system_r:init_t:s0         1 ?        00:00:01 systemd
  5. system_u:system_r:kernel_t:s0       2 ?        00:00:00 kthreadd
  6. system_u:system_r:kernel_t:s0       4 ?        00:00:00 kworker/0:0H
  7. system_u:system_r:kernel_t:s0       5 ?        00:00:00 kworker/u2:0
  8. ...
  9. system_u:system_r:sshd_t:s0-s0:c0.c1023 2344 ? 00:00:00 sshd
  10. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2350 ? 00:00:00 sshd
  11. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2353 pts/0 00:00:00 bash
  12. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2415 pts/0 00:00:00 su
  13. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2424 pts/0 00:00:00 bash
  14. system_u:system_r:kernel_t:s0    2726 ?        00:00:00 kworker/u2:2
  15. system_u:system_r:kernel_t:s0    2778 ?        00:00:00 kworker/0:1
  16. system_u:system_r:kernel_t:s0    2836 ?        00:00:00 kworker/0:3
  17. system_u:system_r:kernel_t:s0    2877 ?        00:00:00 kworker/0:0
  18. system_u:system_r:ksmtuned_t:s0  2885 ?        00:00:00 sleep
  19. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2886 pts/0 00:00:00 ps

  20. # 基本上进程主要分为两大类,
  21. # 一种是系统有受限的 system_u:system_r,
  22. # 另一种可能是用户自己的,比较不受限的进程(通常是本机用户自己执行的程序 ) unconfined_u:unconfined_r

  23. # unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2424 pts/0 00:00:00 bash
  24. # 比如上面这个进程,就是我们自己执行命令所在的 bash
複製代碼

   
基本上,這些對於資料在targeted 政策下的對應對下


[td]
身份識別角色對應在 targeted 的意義
unconfined_uunconfined_r一般可登陸消費者的進程,比較沒有受限的進程。 大多數都是使用者已經順利登陸系統(不論是網路還是本機登陸來取得可用的 shell)後,所用來操作系統的進程,如 bash x window 相關富安居等
system_usystem_r由於為系統帳戶,因此是非交談式的系統運行進程,大多數的系統進程均是這種類型

如上所述,在預設的target 政策下,最重要的是type 字段,主體與目標之間是否具有可讀寫的權限,與進程的domain 與文件的type 有關。這兩者的關係可以使用crond 以及他的配置文件來說明

  1. # 1. 先看看 crond 这个进程的安全本文内容
  2. [root@study ~]# ps -eZ | grep cron
  3. system_u:system_r:crond_t:s0-s0:c0.c1023 1398 ? 00:00:00 atd
  4. system_u:system_r:crond_t:s0-s0:c0.c1023 1400 ? 00:00:00 crond
  5. # 这个安全本文的类型名称为 crond_t 格式

  6. # 2. 看看 /usr/ssbin/crond 、 /etc/cron.d、/etc/cron.d 文件的安全本文内容
  7. [root@study ~]# ll -Zd /usr/sbin/crond /etc/crontab /etc/cron.d
  8. drwxr-xr-x. root root system_u:object_r:system_cron_spool_t:s0 /etc/cron.d
  9. -rw-r--r--. root root system_u:object_r:system_cron_spool_t:s0 /etc/crontab
  10. -rwxr-xr-x. root root system_u:object_r:crond_exec_t:s0 /usr/sbin/crond
複製代碼

   
執行/usr/ssbin/crond後,該程序編程的進程domain類似是crond_t,它能夠讀取的配置文件是system_cron_spool_t類型。因此無論/etc/crontab與/etc/cron.d以及/var/spool/cron都會是相關的SELinux類型(/var/spool/cron為user_cron_spool_t類型)。下面圖示說明



crond 執行後,具有crond_exec_t 類型
該文件類型會造成主體進程Subject 具有crond 這個領域domain,政策針對這個領域有許多規則,其中就包括可以讀取的目標資源類型
由於crond domain被設置為可以讀取system_cron_spool_t類型的目標文件object,因此你的配置文件放到/etc/cron.d/目錄下,就能夠被crond進程讀取了
但是最終能不能讀到正確的資料,還需要看傳統的rwx 是否符合Linux 的權限規範
下面來測試上述說明

  1. # 1. 假设你因为不熟悉的缘故,因此是在 root 家目录建立一个如下的 cron 设置
  2. [root@study ~]# vim checktime
  3. 10 * * * * root sleep 60s

  4. # 2. 发现文件放错目录了,又不想要保留副本,因此使用 mv 移动到正确的目录
  5. [root@study ~]# mv checktime /etc/cron.d/
  6. [root@study ~]# ll /etc/cron.d/checktime
  7. -rw-r--r--. 1 root root 26 Mar 17 13:12 /etc/cron.d/checktime
  8. # 权限是 644,任何进程都可以读取

  9. # 3. 强制重新启动 crond,然后查看登录日志
  10. [root@study ~]# systemctl restart crond         
  11. [root@study ~]# tail /var/log/cron
  12. Mar 17 13:01:01 study run-parts(/etc/cron.hourly)[3889]: finished mcelog.cron
  13. Mar 17 13:10:01 study CROND[3972]: (root) CMD (/usr/lib64/sa/sa1 1 1)
  14. Mar 17 13:14:01 study crond[1400]: ((null)) Unauthorized SELinux context=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 file_context=unconfined_u:object_r:admin_home_t:s0 (/etc/cron.d/checktime)
  15. Mar 17 13:14:01 study crond[1400]: (root) FAILED (loading cron table)
  16. Mar 17 13:15:08 study crond[1400]: (CRON) INFO (Shutting down)
  17. Mar 17 13:15:08 study crond[4073]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 13% if used.)
  18. Mar 17 13:15:08 study crond[4073]: ((null)) Unauthorized SELinux context=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 file_context=unconfined_u:object_r:admin_home_t:s0 (/etc/cron.d/checktime)
  19. Mar 17 13:15:08 study crond[4073]: (root) FAILED (loading cron table)
  20. Mar 17 13:15:08 study crond[4073]: (CRON) INFO (running with inotify support)
  21. Mar 17 13:15:08 study crond[4073]: (CRON) INFO (@reboot jobs will be run at computer's startup.)

  22. # 上述日志中有 Unauthorized 的信息,表示有错误,因为原本的安全本文与文件的实际安全本文无法搭配的缘故,
  23. # 信息还列出了 SELinux context 与 file_context 的信息,表示的确不匹配
複製代碼

   
從如上的測試來看,上述測試由於安全本文不匹配導致進程無法讀取該文件

#SELinux 三種模式的啟動、關閉與觀察
並非所有的Linux distribution 都支持SELinux,CentOS 7.x 本身就有支持SELinux,所以你不需要自行編譯SELinux 到你的Linux 核心中。目前SELinux 是否啟動有三種模式:

enforcing:強制模式,表示SELinux 運行中,且已經正確的開始限制domain/type 了
permissive:寬容模式,表示SELinux 運行中,不過僅有警告進行並不會實際限制domain/type 的存取。這種模式可以用來debug SELinux 的配​​置
disabled:SELinux 關閉中
三種模式的示意圖如下:



注意:並非有所的進程都受SELinux的管控,注意是有受限的進程主體,可以通過ps -eZ來觀察該進程是否有受限(confined)。下面來觀察crond與bash程序是否有被限制

  1. [root@study ~]# ps -eZ | grep -E 'cron|bash'
  2. system_u:system_r:crond_t:s0-s0:c0.c1023 1398 ? 00:00:00 atd
  3. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2353 pts/0 00:00:00 bash
  4. unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2424 pts/0 00:00:00 bash
  5. system_u:system_r:crond_t:s0-s0:c0.c1023 4073 ? 00:00:00 crond
複製代碼

   
因為目前target這個政策下,只有第3個字段type會有影響,因此可以看到crond有crond_t類型,是受限的,而bash是unconfined_t類型,是不受限的,也就是說bash不會經過上圖的流程,而直接去判定rwx

可以通過以下方式獲取當前的SELinux 模式
  1. [root@study ~]# getenforce
  2. Enforcing
複製代碼

   
查詢當前SELinux 的政策(Policy)

  1. sestatus [-vb]

  2. 选项与参数:
  3.         -v:检查 /etc/sestatus.conf 内的文件与进程的安全性本文内容
  4.         -b:将目前政策的规则布尔值列出,即某些规则 rule 是否要启动(0/1)
複製代碼

   
  1. # 范例 1:列出目前 SELinux 使用的哪个政策 Policy

  2. [root@study ~]# sestatus                  
  3. SELinux status:                 enabled                                # SELinux 是否启动
  4. SELinuxfs mount:                /sys/fs/selinux                # SELinux 的相关文件数据挂载点
  5. SELinux root directory:         /etc/selinux                # SELinux 的根目录所在
  6. Loaded policy name:             targeted                        # 当前的政策
  7. Current mode:                   enforcing                        # 当前模式
  8. Mode from config file:          enforcing                        # 目前配置文件内规范的 SELinux 模式
  9. Policy MLS status:              enabled                                # 是否含有 MLS 的模式机制
  10. Policy deny_unknown status:     allowed                                # 是否预设抵挡未知的主体进程
  11. Max kernel policy version:      31
複製代碼

   
上述信息科知道,SELinux 目前的政策是targeted ,可通過如下方式修改

  1. [root@study ~]# vim /etc/selinux/config
  2. # This file controls the state of SELinux on the system.
  3. # SELINUX= can take one of these three values:
  4. #     enforcing - SELinux security policy is enforced.
  5. #     permissive - SELinux prints warnings instead of enforcing.
  6. #     disabled - No SELinux policy is loaded.
  7. SELINUX=enforcing                         # 可选择为上述 3 个
  8. # SELINUXTYPE= can take one of three values:
  9. #     targeted - Targeted processes are protected,
  10. #     minimum - Modification of targeted policy. Only selected processes are protected.
  11. #     mls - Multi Level Security protection.
  12. SELINUXTYPE=targeted                # 可选值为上述 3 个
複製代碼

   
#SElinux 的啟動與關閉
由於SElinux 是整合到核心中去的,因此修改上述配置文件之後,需要重新啟動。

注意:如果從disable轉到啟動SELinux的模式時,由於系統必須要針對文件寫入安全性本文信息,因此開機過程需要耗費不少時間等待重新寫入SELinux安全性本文(有時也稱為SELinux Label) ,而且在寫完之後還需要重新啟動一次,啟動成功之後,再使用getenforce 和 sestatus來觀察是否有成功啟動到Enforcing模式

如果當前已經是Enforcing 模式,可能由於一些設置問題大道至SELinux 讓某些服務無法正常的運行,此時可將模式修改為寬容模式(permissive),讓SELinux 只發出警告信息

  1. setenforce [0|1]

  2. 选项与参数:
  3.         0:转成 permissive 宽容模式
  4.         1:转成 Enforcing 强制模式
  5. 注意:无法在 Disabled 模式下进程模式的切换
複製代碼

   
某些時候從Disabled換成Enforcing之後,有部分服務可能無法順利啟動,可能會報錯/lib/xxx數據沒有權限讀取的錯誤信息。這大多數是由於重新寫入Selinux type(Relabel)出錯的原因,使用Permissive模式就沒有該錯誤。最簡單的辦法是在Permissive模式下使用指令restorecon -Rv /重新還原所有SELinux的類型

#SELinux 政策內的規則管理
#SELinux 各個規則的布爾值查詢:getsebool
  1. getsebool [-a] [规则名称]

  2. 选项与参数:
  3.         -a:列出目前系统上所有 SELinux 规则的布尔值为开启或关闭(on/off)
複製代碼

   
# 范例 1:查询所有的布尔值设置
  1. # 范例 1:查询所有的布尔值设置
  2. [root@study ~]# getsebool -a
  3. abrt_anon_write --> off
  4. abrt_handle_event --> off
  5. abrt_upload_watch_anon_write --> on
  6. ...
  7. cron_can_relabel --> off                # 这个与 cron 有关
  8. cron_system_cronjob_use_shares --> off
  9. cron_userdomain_transition --> on
  10. ...
  11. httpd_anon_write --> off                # 与网页 http 有关
  12. httpd_builtin_scripting --> on
  13. httpd_can_check_spam --> off
  14. # 每一行都是一个规则
複製代碼

   
#SELinux 各個規則規範的主體進程能夠讀取的文件SELinux type 查詢seinfo、sesearch
上述指令知道了所有的規則開啟情況,可以通過seinfo、sesearch 等工具來查看每個規則具體在限制什麼。

上述工具並未預裝,請拿出安裝光盤掛載到/mnt目錄下,安裝

  1. [root@study ~]# blkid
  2. /dev/sr0: UUID="2019-09-11-18-50-31-00" LABEL="CentOS 7 x86_64" TYPE="iso9660" PTTYPE="dos"
  3. /dev/sda1: UUID="e9d54afb-2afe-42de-87fe-9f55d747fcd9" TYPE="xfs"
  4. /dev/sda2: UUID="CNUXwS-J3Lh-0nDA-TssW-l1vT-90us-MHYnT1" TYPE="LVM2_member"
  5. /dev/mapper/centos_study-root: UUID="d7e09bb4-2f04-4ed4-b377-91a22fe85ce7" TYPE="xfs"
  6. /dev/mapper/centos_study-swap: UUID="684eebc0-3f70-4fc1-9a5d-d683f6a07cd0" TYPE="swap"
  7. [root@study ~]# mount /dev/sr0 /mnt/
  8. mount: /dev/sr0 is write-protected, mounting read-only
  9. [root@study ~]# yum install /mnt/Packages/setools-console-*                              
  10. ...
  11. Complete!
  12. [root@study ~]# umount /mnt/  # 卸载光盘
複製代碼

   
  1. seinfo [-Atrub]

  2. 选项与参数:
  3.         -A:列出 SELinux 的状态、规则布尔值、身份识别、角色、类型等所有信息
  4.         -u:列出 SELinux 的所有身份识别 user 种类
  5.         -r:列出 SELinux 的所有角色 role 种类
  6.         -t:列出 SELinux 的所有类型 type 种类
  7.         -b:列出所有规则的种类(布尔值)
複製代碼

   
  1. # 范例 1:列出 SELinux 在此政策下的统计状态
  2. [root@study ~]# seinfo

  3. Statistics for policy file: /sys/fs/selinux/policy
  4. Policy Version & Type: v.31 (binary, mls)

  5.    Classes:           130    Permissions:       272
  6.    Sensitivities:       1    Categories:       1024
  7.    Types:            4792    Attributes:        253
  8.    Users:               8    Roles:              14
  9.    Booleans:          316    Cond. Expr.:       362
  10.    Allow:          107360    Neverallow:          0
  11.    Auditallow:        157    Dontaudit:       10020
  12.    Type_trans:      18129    Type_change:        74
  13.    Type_member:        35    Role allow:         39
  14.    Role_trans:        416    Range_trans:      5899
  15.    Constraints:       143    Validatetrans:       0
  16.    Initial SIDs:       27    Fs_use:             32
  17.    Genfscon:          103    Portcon:           614
  18.    Netifcon:            0    Nodecon:             0
  19.    Permissives:         0    Polcap:              5
  20.    
  21. # 当前政策是 targeted ? (哪里显示的?),此政策下的 Types 类型有 4792 个
  22. # SELinux 的规则(Booleans)有 316 条
複製代碼

   
在前面讲到过几个身份识别 user 与 角色 role,seinfo 可以查询到所有的种类,可自行查询

在前面讲到 /etc/cron.d/checktime 的 SElinux type 类型不太对,我们知道 crond 进程的 type 是 crond_t,那么查找下 crond_t 能够读取的文件 SELinux type 有哪些

  1. sesearch [-A] [-s 主体类别] [-t 目标类别] [-b 布尔值]

  2. 选项与参数:
  3.         -A:列出后面数据中,允许「读取或放行」的相关数据
  4.         -t:后面还要接 type、例如 -t httpd_t
  5.         -b:后面接 SELinux 的规则,例如 -b httpd_enable_ftp_server
複製代碼

   
# 范例 1:找出 crond_t 主体进程能够读取的文件 SELinux type

  1. # 范例 1:找出 crond_t 主体进程能够读取的文件 SELinux type

  2. [root@study ~]# sesearch -A -s crond_t | grep spool
  3.    allow crond_t var_spool_t : dir { ioctl read getattr lock search open } ;
  4.    allow crond_t system_cron_spool_t : dir { ioctl read getattr lock search open } ;
  5.    allow crond_t user_cron_spool_t : lnk_file { read getattr } ;
  6.    allow crond_t user_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
  7.    allow crond_t system_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
  8.    allow crond_t var_spool_t : file { ioctl read getattr lock open } ;
  9.    allow crond_t cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
  10.    allow daemon user_cron_spool_t : file { ioctl read write getattr lock append } ;
  11.    allow crond_t cron_spool_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
  12.    allow crond_t user_cron_spool_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
  13.    allow crond_t user_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
  14.    allow crond_t system_cron_spool_t : file { ioctl read write create getattr setattr lock append unlink link rename open } ;
  15.    
  16. # allow 后面是主体进程以及文件的 SELinux type,上面数据是截取出来的
  17. # crond_t 可以读取 system_cron_spool_t 的文件/目录类型等

  18. # 范例 2:找出 crond_t 是否能读取 /etc/cron.d/checktime 这个我们自定义的配置文件?
  19. [root@study ~]# ll -Z /etc/cron.d/checktime
  20. -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 /etc/cron.d/checktime
  21. # 两个重点:SELinux type 为 admin_home_t,一个是文件(file)

  22. [root@study ~]# sesearch -A -s crond_t | grep admin_home_t
  23.    allow domain admin_home_t : dir { getattr search open } ;
  24.    allow crond_t admin_home_t : dir { ioctl read getattr lock search open } ;
  25.    allow userdom_filetrans_type admin_home_t : lnk_file { read getattr } ;
  26.    allow userdom_filetrans_type admin_home_t : dir { ioctl read write getattr lock add_name remove_name search open } ;
  27.    allow domain admin_home_t : lnk_file { read getattr } ;
  28.    allow crond_t admin_home_t : lnk_file { read getattr } ;
  29.    
  30. # 发现有 crond_t admin_home_t 存在,不过这个是总体的信息
  31. # 没有针对某些规则的查询,所以不能确定 checktime 能否被读取,但是基本上就是 SELinux type 出现问题,才无法读取的
複製代碼

   
現在知道了/etc/cron.d/checktime是SELinux type錯誤導致無法讀取的。看來在getsebool -a中看到的httpd_enable_homedirs是什麼?又是規範了哪些主體進程能夠讀取的SELinux type

  1. [root@study ~]# semanage boolean -l | grep httpd_enable_homedirs
  2. httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs
  3. # httpd_enable_homedirs 的功能是允许 httpd 进程读取用户家目录

  4. # 范例 3:列出该规则中,主体进程能够读取的文件  SELinux type
  5. [root@study ~]# sesearch -A -b httpd_enable_homedirs
  6. Found 77 semantic av rules:
  7.    allow httpd_t user_home_type : lnk_file { read getattr } ;
  8.    allow httpd_suexec_t user_home_type : lnk_file { read getattr } ;
  9.    allow httpd_suexec_t user_home_dir_t : lnk_file { read getattr } ;
  10.    allow httpd_t nfs_t : lnk_file { read getattr } ;
  11.    allow httpd_sys_script_t nfs_t : file { ioctl read getattr lock open } ;
  12.    allow httpd_sys_script_t cifs_t : lnk_file { read getattr } ;
  13.    allow httpd_user_script_t user_home_type : lnk_file { read getattr } ;
  14.    allow httpd_user_script_t user_home_type : dir { getattr search open } ;
  15.    allow httpd_t cifs_t : file { ioctl read getattr lock open } ;
  16.    allow httpd_sys_script_t nfs_t : dir { getattr search open } ;
  17.    allow httpd_sys_script_t nfs_t : dir { ioctl read getattr lock search open } ;
  18.    allow httpd_sys_script_t nfs_t : dir { getattr search open } ;
  19.    allow httpd_sys_script_t nfs_t : dir { ioctl read getattr lock search open } ;
  20.    allow httpd_t user_home_dir_t : dir { getattr search open } ;
  21.    allow httpd_sys_script_t cifs_t : file { ioctl read getattr lock open } ;
  22.    allow httpd_sys_script_t user_home_dir_t : dir { getattr search open } ;
  23.    allow httpd_sys_script_t user_home_dir_t : lnk_file { read getattr } ;
  24.    xxx
  25. # 从上面的数据才可以理解,主要是放行 httpd_t 能否读取用户家目录的文件 (笔者这里是懵逼的没有看出来)
  26. # 所以,如果该规则没有启动,基本上 httpd_t 这种进程就无法读取用户家目录下的文件
複製代碼

   
#修改SELinux 規則的布爾值setsebool
查詢到某個SELinux rule ,並且以seaserch 知道該規則的用途後,可以通過下面的方式來管理

  1. setsebool [-p] [规则名称][0|1]

  2. -P:直接将设置值写入配置文件,该设置数据未来会生效
複製代碼

   
  1. # 范例 1:查询 httpd_enable_homedirs 这个规则的状态,并且修改这个规则为不同的布尔值
  2. [root@study ~]# getsebool httpd_enable_homedirs
  3. httpd_enable_homedirs --> off                        # 关闭状态
  4. [root@study ~]# setsebool -P httpd_enable_homedirs 1                # 开启它
  5. [root@study ~]# getsebool httpd_enable_homedirs
  6. httpd_enable_homedirs --> on
複製代碼

#SELinux 安全本文的修改
SELinux 對受限的主體進程沒有影響:

考慮SELinux 的三種類型
考慮SELinux的政策規則是否放行
比對SELinux type 關係
上面講解過可以通過sesearch 來找到主體進程與文件的SELinux type 關係,那麼怎麼修改文件的SELinux type,能讓主體進程讀到呢?

#使用chcon 手動修改文件的SELinux type
  1. chcon [-R] [-t type] [-u user] [-r role] 文件
  2. chcon [-R] --reference=范例文件 文件

  3. 选项与参数:
  4.         -R:连同该目录下的次目录也同时修改
  5.         -t:后面接安全性本文的类型字段,例如 httpd_sys_content_t
  6.         -u:后面接身份识别,例如 system_u (不重要)
  7.         -r:后面接角色,例如 system_r (不重要)
  8.         -v:若有变化成功,将变动的结果列出来
  9.         --reference=文件:拿某个文件档范例来修改后续接的文件的类型
複製代碼

   
  1. # 范例 1:查询 /etc/hosts 的 SELinux type,并将该类型套用到 /etc/cron.d/checktime 上
  2. [root@study ~]# ll -Z /etc/hosts
  3. -rw-r--r--. root root system_u:object_r:net_conf_t:s0  /etc/hosts
  4. # net_conf_t 是上面文件中的类型
  5. [root@study ~]# chcon -v -t net_conf_t /etc/cron.d/checktime
  6. changing security context of '/etc/cron.d/checktime'
  7. [root@study ~]# ll -Z /etc/cron.d/checktime
  8. -rw-r--r--. root root unconfined_u:object_r:net_conf_t:s0 /etc/cron.d/checktime

  9. # 范例 2:直接以 /etc/shadow 的 type 套用
  10. [root@study ~]# chcon -v --reference=/etc/shadow /etc/cron.d/checktime
  11. changing security context of '/etc/cron.d/checktime'
  12. [root@study ~]# ll -Z /etc/shadow /etc/cron.d/checktime
  13. -rw-r--r--. root root system_u:object_r:shadow_t:s0    /etc/cron.d/checktime
  14. ----------. root root system_u:object_r:shadow_t:s0    /etc/shadow
複製代碼

   
上面的示例並不能解決crond不能讀取/etc/cron.d/checktime的問題,因為需要改成/etc/cron.d下的標準type才行。可以使用restorecon來讓SELinux自己默認解決目錄下的type問題

#使用restorecon 讓文件恢復正確的SELinux type
  1. restorecon [-Rv] 文件或目录

  2. 选项与参数:
  3.         -R:连同次目录一起修改
  4.         -v:将过程显示到屏幕上
複製代碼

   
  1. # 范例 3:将 /etc/cron.d/ 下的文件都恢复成预设的 SELinux type
  2. [root@study ~]# restorecon -Rv /etc/cron.d/
  3. restorecon reset /etc/cron.d/checktime context system_u:object_r:shadow_t:s0->system_u:object_r:system_cron_spool_t:s0

  4. # 上面将  shadow_t 改成了 system_cron_spool_t 类型

  5. # 范例 4:重新启动 crond 看看有没有正确启动 checktime
  6. [root@study ~]# systemctl restart crond         
  7. [root@study ~]# tail /var/log/cron
  8. Mar 17 16:01:01 study CROND[5886]: (root) CMD (run-parts /etc/cron.hourly)
  9. Mar 17 16:01:01 study run-parts(/etc/cron.hourly)[5886]: starting 0anacron
  10. Mar 17 16:01:01 study run-parts(/etc/cron.hourly)[5898]: finished 0anacron
  11. Mar 17 16:01:01 study run-parts(/etc/cron.hourly)[5886]: starting mcelog.cron
  12. Mar 17 16:01:01 study run-parts(/etc/cron.hourly)[5904]: finished mcelog.cron
  13. Mar 17 16:10:01 study CROND[5989]: (root) CMD (/usr/lib64/sa/sa1 1 1)
  14. Mar 17 16:12:48 study crond[4073]: (CRON) INFO (Shutting down)
  15. Mar 17 16:12:48 study crond[6068]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 62% if used.)
  16. Mar 17 16:12:49 study crond[6068]: (CRON) INFO (running with inotify support)
  17. Mar 17 16:12:49 study crond[6068]: (CRON) INFO (@reboot jobs will be run at computer's startup.)
  18. # 没有报错信息
複製代碼

   
從這裡看來restorecon 很方便,chcon 還是比較麻煩的

#semanage 默認目錄的安全性本文查詢與修改
為什麼restorecon 可以恢復原本的SELinux type 呢?那一定是有個地方在記錄每個文件/目錄的SELinux 默認類型

如何查詢預設的SELinux type
如何增加、修改、刪除預設的SELinux type
  1. semanage {login|user|port|interface|fcontext|translation} -l
  2. semanage fcontext -{a|d|m} [-frst] file_spec

  3. 选项与参数:
  4.         fcontext:主要用在安全性本文方面的用途, -l 为查询
  5.         -a:增加;可以增加一些目录的默认安全性本文类型设置
  6.         -m:修改
  7.         -d:删除
複製代碼
  1. # 范例 1:查询 /etc/   /etc/cron.d/ 的预设 SELinux type
  2. [root@study ~]# semanage fcontext -l | grep -E '^/etc |^/etc/cron'
  3. /etc/cron.daily(/.*)?                              all files          system_u:object_r:bin_t:s0
  4. /etc/cron.weekly(/.*)?                             all files          system_u:object_r:bin_t:s0
  5. /etc/cron.hourly(/.*)?                             all files          system_u:object_r:bin_t:s0
  6. /etc/cron.monthly(/.*)?                            all files          system_u:object_r:bin_t:s0
  7. /etc/cron.minutely/openshift-facts                 regular file       system_u:object_r:openshift_cron_exec_t:s0
  8. /etc/cron\.(daily|monthly)/acct                    regular file       system_u:object_r:acct_exec_t:s0
  9. /etc/cron\.(daily|weekly)/sysklogd                 regular file       system_u:object_r:logrotate_exec_t:s0
  10. /etc/cron\.(daily|monthly)/mailman                 regular file       system_u:object_r:mailman_queue_exec_t:s0
  11. /etc/cron\.(daily|weekly)/man-db.*                 regular file       system_u:object_r:mandb_exec_t:s0
  12. /etc/cron\.(daily|monthly)/radiusd                 regular file       system_u:object_r:radiusd_exec_t:s0
  13. /etc/cron\.(daily|weekly)/ntp-simple               regular file       system_u:object_r:ntpd_exec_t:s0
  14. /etc/cron\.(daily|weekly)/ntp-server               regular file       system_u:object_r:ntpd_exec_t:s0
  15. /etc/cron\.((daily)|(weekly)|(monthly))/freeradius regular file       system_u:object_r:radiusd_exec_t:s0
  16. /etc/cron\.d(/.*)?                                 all files          system_u:object_r:system_cron_spool_t:s0
  17. /etc/cron\.daily/[sm]locate                        regular file       system_u:object_r:locate_exec_t:s0
  18. /etc/cron\.weekly/(c)?fingerd                      regular file       system_u:object_r:fingerd_exec_t:s0
  19. /etc                                               all files          system_u:object_r:etc_t:s0
  20. /etc/crontab                                       regular file       system_u:object_r:system_cron_spool_t:s0
  21. /etc/cron\.daily/prelink                           regular file       system_u:object_r:prelink_cron_system_exec_t:s0
  22. /etc/cron\.daily/calamaris                         regular file       system_u:object_r:calamaris_exec_t:s0
  23. /etc/cron\.daily/certwatch                         regular file       system_u:object_r:certwatch_exec_t:s0
  24. /etc/cron\.monthly/proftpd                         regular file       system_u:object_r:ftpd_exec_t:s0
複製代碼

看/etc/cron\.d(/.*)? all files system_u:object_r:system_cron_spool_t:s0 這一行,這也是為什麼直接使用vim在/etc/cron.d下新建文件時,預設SELinux type是正確的。

練習:下面要建立一個/srv/mycron目錄,默認也是需要變成system_cron_spool_t時

  1. # 1. 先建立 mycron 目录,再放入配置文件,观察 SELinux type
  2. [root@study ~]# mkdir /srv/mycron
  3. [root@study ~]# cp /etc/cron.d/checktime /srv/mycron/
  4. [root@study ~]# ll -dZ /srv/mycron/ /srv/mycron/checktime
  5. drwxr-xr-x. root root unconfined_u:object_r:var_t:s0   /srv/mycron/
  6. -rw-r--r--. root root unconfined_u:object_r:var_t:s0   /srv/mycron/checktime
  7. # 发现变成了 var_t

  8. # 2. 观察上层 /srv 的 SELinux type
  9. [root@study ~]# semanage fcontext -l | grep '^/srv'
  10. /srv/.*                                            all files          system_u:object_r:var_t:s0
  11. /srv/([^/]*/)?www(/.*)?                            all files          system_u:object_r:httpd_sys_content_t:s0
  12. /srv/([^/]*/)?ftp(/.*)?                            all files          system_u:object_r:public_content_t:s0
  13. /srv/([^/]*/)?rsync(/.*)?                          all files          system_u:object_r:public_content_t:s0
  14. /srv/([^/]*/)?www/logs(/.*)?                       all files          system_u:object_r:httpd_log_t:s0
  15. /srv/node(/.*)?                                    all files          system_u:object_r:swift_data_t:s0
  16. /srv/gallery2(/.*)?                                all files          system_u:object_r:httpd_sys_content_t:s0
  17. /srv/lib/gitosis(/.*)?                             all files          system_u:object_r:gitosis_var_lib_t:s0
  18. /srv/gallery2/smarty(/.*)?                         all files          system_u:object_r:httpd_sys_rw_content_t:s0
  19. /srv/loopback-device(/.*)?                         all files          system_u:object_r:swift_data_t:s0
  20. /srv                                               all files          system_u:object_r:var_t:s0
  21. # 可以看到这里默认就是  var_t 类型的

  22. # 3. 将 mycron 默认值改为 system_cron_spool_t
  23. [root@study ~]# semanage fcontext -a -t system_cron_spool_t "/srv/mycron(/.*)?"
  24. [root@study ~]# semanage fcontext -l | grep '^/srv/mycron'
  25. /srv/mycron(/.*)?                                  all files          system_u:object_r:system_cron_spool_t:s0

  26. # 4. 回复 /srv/mycron 以及子目录相关的 SELinux type
  27. [root@study ~]# restorecon -Rv /srv/mycron/
  28. restorecon reset /srv/mycron context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:system_cron_spool_t:s0
  29. restorecon reset /srv/mycron/checktime context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:system_cron_spool_t:s0
複製代碼

通過這個例子來看,restorecon 的確是很方便,學會這些基礎的工具,對於SELinux 來說基本上也夠用了

#一個網絡服務案例及登錄文件協助
本章在SELinux 小節中介紹到的各個指令,尤其是setsebool、chcon、restorecon 等都是為了當你的某些網絡服務無法正常提供相關功能時,才需要進行修改的一些指令動作。

可以通過主動檢查的方式來檢查是否有SELinux 產生的錯誤。而不是等客戶端聯機失敗來反饋

#setroubleshoot:錯誤信息寫入 /var/log/messages
幾乎所有SELinux相關的程序都是以se開頭,該服務時錯誤克服,啟動後,會將關於SELinux的錯誤信息與克服方法記錄到/var/log/messages與/var/log/setroubleshoot/*中

需要安装:setroubleshoot 与 setroubleshoot-server。原本 SELinux 信息是两个服务来记录的,分别是 auditd 与 setroubleshoot。在 CentOS 6.x 起整合成 auditd 了。所以安装好 setroubleshoot-server 后,需要重新启动 auditd 服务,否则 setroubleshoot 功能不会被启动

实际上。CentOS 7.x 对 setroubleshoot 的运行方式是:先由 auditd 去呼叫 audispd 服务,然后 audispd 服务启动 sedispatch 程序, sedispatch 再将原本的 auditd 信息转成 setroubleshoot 的信息,存储下来

  1. [root@study ~]# rpm -qa | grep setroubleshoot
  2. setroubleshoot-3.2.30-7.el7.x86_64
  3. setroubleshoot-plugins-3.0.67-4.el7.noarch
  4. setroubleshoot-server-3.2.30-7.el7.x86_64
複製代碼

   
在预设的情况下 setroubleshoot 被安装了,记得刚安装 setroubleshoot 的话,需要重新启动 auditd 服务的、

目前我们没有任何受限的网络服务主体进程在运行,下面使用一个简单的 FTP 服务器软件示例,来了解上面讲到的许多重点应用

#实例说明:通过 vsftpd 这个 FTP 服务器来存取系统上的文件
在 CentOS 7.x 环境下, FTP 的默认服务器软件主要是 vsftpd

详细的 FTP 协议在服务器篇讲解,这里简单利用 vsftpd 与 FTP 的协议来讲解 SELinux 的问题与错误克服。

下面只接受一些简单的 FTP 知识:客户端需要使用 FTP 账户登录 FTP 服务器,有一个称为「匿名 (anonymous)」的账户可以登录系统,但是这个匿名的账户登录后,只能存取一个特定的目录,而无法脱离该目录

在 vsftpd 中,一般用户与匿名者的家目录说明如下:

匿名者:如果使用瀏覽器來聯機到FTP服務器,那預設就是使用匿名者登錄系統。匿名者的家目錄默認是在/var/ftp中,同時,匿名者在家目錄下只能下載數據,不能上傳數據到FTP服務器,同時匿名者無法離開FTP服務器的/var/ftp目錄
一般FTP 賬戶:在預設情況下,所有UID 大於1000 的賬戶,都可以使用FTP 來登錄系統,登錄系統後,所有的賬戶都能夠取得自己家目錄下的文件數據,預設也可以上傳、下載文件的
為了避免與之前章節的用戶產生誤解情況,創建一個名為ftptest 的賬戶,且賬戶密碼為myftp123

  1. [root@study ~]# useradd -s /sbin/nologin ftptest
  2. [root@study ~]# echo "myftp123" | passwd --stdin ftptest
  3. Changing password for user ftptest.
  4. passwd: all authentication tokens updated successfully.
複製代碼

   
下面來安裝vsftp 服務器軟件(還是在光盤中安裝,前面掛載那樣)

  1. [root@study ~]# yum install /mnt/Packages/vsftpd-3*                    

  2. [root@study ~]# systemctl start vsftpd                # 启动 vsftpd 服务
  3. [root@study ~]# systemctl enable vsftpd                # 设置为开机启动
  4. Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.
  5. [root@study ~]# netstat -tlnp
  6. Active Internet connections (only servers)
  7. Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name   
  8. tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1374/cupsd         
  9. tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1578/master         
  10. tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      2350/sshd: mrcode@p
  11. tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1/systemd           
  12. tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      1975/dnsmasq        
  13. tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1378/sshd           
  14. tcp6       0      0 ::1:631                 :::*                    LISTEN      1374/cupsd         
  15. tcp6       0      0 ::1:25                  :::*                    LISTEN      1578/master         
  16. tcp6       0      0 ::1:6010                :::*                    LISTEN      2350/sshd: mrcode@p
  17. tcp6       0      0 :::111                  :::*                    LISTEN      1/systemd           
  18. tcp6       0      0 :::21                   :::*                    LISTEN      6656/vsftpd         
  19. tcp6       0      0 :::22                   :::*                    LISTEN      1378/sshd

  20. # 可以看到   6656/vsftpd 这行数据,代表已经启动了
複製代碼

   
#匿名者無法下載的問題
模擬一些FTP的常用狀態,假設將/etc/securetty以及主要的/etc/sysctl.conf放置給所有人下載,那麼可以能會這樣做

  1. [root@study ~]# cp -a /etc/securetty /etc/sysctl.conf /var/ftp/pub
  2. [root@study ~]# ll /var/ftp/pub/
  3. total 8
  4. -rw-------. 1 root root 221 Oct 31  2018 securetty
  5. -rw-r--r--. 1 root root 449 Aug  9  2019 sysctl.conf

複製代碼

   
一般來說,默認要給用戶下載的FTP文件會放在/var/ftp/pub目錄中。下面使用簡單的終端機瀏覽器curl來觀察

  1. # 1. 查看 FTP 根目录下有哪些内容
  2. [root@study ~]# curl ftp://localhost
  3. drwxr-xr-x    2 0        0              42 Mar 17 09:03 pub
  4. # 确实看到了 pub 目录

  5. # 2. 查看 pub 目录内的内容
  6. [root@study ~]# curl ftp://localhost/pub
  7. curl: (78) RETR response: 550
  8. # 无法访问,是因为 pub 是一个目录需要后缀 / 结尾
  9. [root@study ~]# curl ftp://localhost/pub/
  10. -rw-------    1 0        0             221 Oct 30  2018 securetty
  11. -rw-r--r--    1 0        0             449 Aug 08  2019 sysctl.conf

  12. # 3. 查看里面的文件内容
  13. [root@study ~]# curl ftp://localhost/pub/sysctl.conf
  14. # sysctl settings are defined through files in
  15. # /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
  16. #
  17. # Vendors settings live in /usr/lib/sysctl.d/.
  18. # To override a whole file, create a new file with the same in
  19. # /etc/sysctl.d/ and put new settings there. To override
  20. # only specific settings, add a file with a lexically later
  21. # name in /etc/sysctl.d/ and put new settings there.
  22. #
  23. # For more information, see sysctl.conf(5) and sysctl.d(5).

  24. # 上面不是错误信息,是哪个文件的内容

  25. # 4. 继续查看下一个文件内容
  26. [root@study ~]# curl ftp://localhost/pub/securetty  
  27. curl: (78) RETR response: 550
  28. # 这里看不到了,但是 securetty 的确是一个文件而不是一个目录,基本原因应该是权限问题
  29. # 因为 vsftpd 默认放在 /var/ftp/pub 内的资料,无论什么 SELinux type 几乎都可以被读取才对

  30. # 5. 修正权限后,再观察一次 securetty 文件
  31. [root@study ~]# ll /var/ftp/pub/
  32. total 8
  33. -rw-------. 1 root root 221 Oct 31  2018 securetty
  34. -rw-r--r--. 1 root root 449 Aug  9  2019 sysctl.conf
  35. # 可以看到 securetty 的其他人权限没有。改变成其他人也可以读取
  36. [root@study ~]# chmod a+r /var/ftp/pub/securetty
  37. [root@study ~]# curl ftp://localhost/pub/securetty
  38. console
  39. vc/1
  40. vc/2
  41. vc/3
  42. # 此时已经能看到文件内容了

  43. # 6. 修正 SELinux type 的内容(非必须)
  44. [root@study ~]# restorecon -Rv /var/ftp/
  45. restorecon reset /var/ftp/pub/securetty context system_u:object_r:etc_runtime_t:s0->system_u:object_r:public_content_t:s0
  46. restorecon reset /var/ftp/pub/sysctl.conf context system_u:object_r:system_conf_t:s0->system_u:object_r:public_content_t:s0
複製代碼

   
上述列子告訴我們,要先從權限角度來檢查,如果無法被讀取,可能是因為沒有r 或則沒有rx 權限,並不一定是SELinux 引起的。下面看看用一般賬戶登錄

#無法從家目錄下載文件的問題分析與解決
由於通過一般賬戶,前面建立的ftptest 賬戶登錄的話,文字型的FTP 客戶端軟件,默認會將用戶引導在根目錄,而不是家目錄,因此,訪問的URL 需要更改一下

  1. # 0. 在 ftptest 家目录下创建一些数据
  2. [root@study ~]# echo  ~ftptest/
  3. /home/ftptest/
  4. [root@study ~]# echo "testing" >  ~ftptest/test.txt
  5. [root@study ~]# cp -a /etc/hosts /etc/sysctl.conf ~ftptest/
  6. [root@study ~]# ll ~ftptest/
  7. total 12
  8. -rw-r--r--. 1 root root 158 Jun  7  2013 hosts
  9. -rw-r--r--. 1 root root 449 Aug  9  2019 sysctl.conf
  10. -rw-r--r--. 1 root root   8 Mar 17 17:23 test.txt

  11. # 1. 一般账户直接登录 FTP 服务器,同时变换目录到家目录
  12. [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/
  13. curl: (67) Access denied: 530                        # 这里报错了
  14. # 注意:书上在增加 ftptest 用户的时候,使用的是 /sbin/nologin,就无法访问 ftp,这里修改下,就可以了
  15. [root@study ~]# usermod -s  /bin/bash ftptest
  16. [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/
  17. -rw-r--r--    1 0        0             158 Jun 07  2013 hosts
  18. -rw-r--r--    1 0        0             449 Aug 08  2019 sysctl.conf
  19. -rw-r--r--    1 0        0               8 Mar 17 09:23 test.txt
  20. # 看左边的权限也是没有问题的
  21. # 从这里开始,笔者的实验和书上的结果对不上了,下面只记录书上的操作指令
  22. # 就是因为上面修改用户的 bash 后,虽然可以访问了,但是下面的却可以下载文件,无法达到和书上的效果一样

  23. # 2. 下载上面可以阅读的权限文件
  24. [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt
  25. curl:(78) RETR response:550
  26. # 无法访下载,是否是 SELinux 造成的?

  27. # 3. 将 SELinux 从 Enforce 转成 Permissive
  28. [root@study ~]# setenforce 0
  29. [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt
  30. testing
  31. [root@study ~]# setenforce 1        # 确定是 SELinux 权限问题后,改回来
  32. # 需要该规则还是该 type?现在不知道
  33. # 所以先查询下登录日志有没有相关的信息提供给我们处理

  34. [root@study ~]# vim /var/log/messages
  35. Aug 9 02:55:58 station3-39 setroubleshoot:SELinux is preventing /usr/sbin/vsftpd
  36.         from lock access on the file /home/ftptest/test.txt. For complete SELinux messages.
  37.         run sealert -l 3axxxxxxxx
  38. # 之类的字样,关键词就是 sealert ,执行这条命令
  39. [root@study ~]# sealert -l 3axxxxxxxx
  40. SELinux is preventing /usr/sbin/vsftpd from lock access on the file /home/ftptest/test/txt.
  41. # 下面说有 47.5% 的几率是由于这个原因所发生,并且可以使用 setsebool 去解决的意思
  42. ******* Plugin catchall_boolean(47.5 confidence) suggests ********

  43. if you want to allow ftp to home dir
  44. ...
  45. Do
  46. setsebool -P ftp_home_dir 1

  47. ******* Plugin catchall(6.38confidence) suggests ********
  48. DO
  49. # grep vsftpd /var/log/audit/audit.log | audit2allow -M mypol
  50. # semodule -i mypol.pp

  51. # 下面就重要了,是整个问题发生的主要原因
  52. Additional Information:
  53. Source Context        system_u:system_r:ftpd_t:s0-s0:c0.c1023
  54. Target Context        unconfined_u:object_r:user_home_t:s0
  55. Target Objects        /home/ftptest/test/txt [ file ]

複製代碼

   
通過上面的測試,知道主要的問題發生在SElinux 的type 不是vsftpd_t 所能讀取的原因,上面47.5 的概率問題,ftp_home_dir 是SELinux rules 的配置

  1. # 1. 确认下 SELinux 的模式,并且无法访问
  2. [root@study ~]# getenforce
  3. Enforcing
  4. [root@study ~]# curl ftp://ftptest:myftp123@localhost/~/test.txt
  5. curl:(78) RETR response:550
  6. [root@study ~]# setsebool -P ftp_home_dir 1
  7. Boolean ftp_home_dir is not defined
  8. # 可惜笔者这里提示没有被定义,与书上对不上啊
複製代碼

   
#一般賬戶用戶從非正規目錄上傳/下載文件
提供/srv/gogogo目錄給ftptest用戶使用,該如何處理?假設不考慮SELiunx的話,就是如下方式

  1. # 1. 处理好所需要的目录数据
  2. [root@study ~]# mkdir /srv/gogogo
  3. [root@study ~]# chgrp ftptest /srv/gogogo/
  4. # 把用户组改成 ftptest 这个组
  5. [root@study ~]# ll -d /srv/gogogo/
  6. drwxr-xr-x. 2 root ftptest 22 3月  17 22:43 /srv/gogogo/
  7. [root@study ~]# echo "test" > /srv/gogogo/test.txt
  8. [root@study ~]# curl ftp://ftptest:myftp123@localhost//srv/gogogo/test.txt
  9. curl: (78) RETR response: 550
  10. # 访问不了,查看日志
  11. [root@study ~]# grep sealert /var/log/messages | tail
  12. Mar 17 22:46:35 study setroubleshoot: SELinux is preventing /usr/sbin/vsftpd from read access on the file test.txt. For complete SELinux messages run: sealert -l 88f08c09-c510-4518-bbcc-58bcee06ffb0

  13. [root@study ~]# sealert -l 88f08c09-c510-4518-bbcc-58bcee06ffb0
  14. SELinux is preventing /usr/sbin/vsftpd from read access on the file test.txt.

  15. # 虽然这个可信度很高,不过,因为会全部方向 FTP,所以不考虑
  16. *****  Plugin catchall_boolean (57.6 confidence) suggests   ******************

  17. If you want to allow ftpd to full access
  18. Then you must tell SELinux about this by enabling the 'ftpd_full_access' boolean.

  19. Do
  20. setsebool -P ftpd_full_access 1

  21. # 因为是非正规目录的使用,所以这边加上预设 SELinux type 恐怕能解决
  22. *****  Plugin catchall_labels (36.2 confidence) suggests   *******************

  23. If you want to allow vsftpd to have read access on the test.txt file
  24. Then you need to change the label on test.txt
  25. Do
  26. # 下面这一条数据
  27. # semanage fcontext -a -t FILE_TYPE 'test.txt'
  28. .... 很多数据
  29. Then execute:
  30. restorecon -v 'test.txt'                # 还有这一条数据,都是要参考的解决方案

  31. *****  Plugin catchall (7.64 confidence) suggests   **************************

  32. If you believe that vsftpd should be allowed read access on the test.txt file by default.
  33. Then you should report this as a bug.
  34. You can generate a local policy module to allow this access.
  35. Do
  36. allow this access for now by executing:
  37. # ausearch -c 'vsftpd' --raw | audit2allow -M my-vsftpd
  38. # semodule -i my-vsftpd.pp


  39. Additional Information:
  40. Source Context                system_u:system_r:ftpd_t:s0-s0:c0.c1023
  41. Target Context                unconfined_u:object_r:var_t:s0
  42. Target Objects                test.txt [ file ]
  43. Source                        vsftpd
  44. Source Path                   /usr/sbin/vsftpd
  45. Port                          <Unknown>
  46. Host                          study.centos.mrcode
  47. Source RPM Packages           
  48. Target RPM Packages           
  49. Policy RPM                    selinux-policy-3.13.1-252.el7.noarch
  50. Selinux Enabled               True
  51. Policy Type                   targeted
  52. Enforcing Mode                Enforcing
  53. Host Name                     study.centos.mrcode
  54. Platform                      Linux study.centos.mrcode 3.10.0-1062.el7.x86_64
  55.                               #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64
  56. Alert Count                   2
  57. First Seen                    2020-03-17 22:46:17 CST
  58. Last Seen                     2020-03-17 22:46:32 CST
  59. Local ID                      88f08c09-c510-4518-bbcc-58bcee06ffb0

  60. Raw Audit Messages
  61. type=AVC msg=audit(1584456392.386:979): avc:  denied  { read } for  pid=10979 comm="vsftpd" name="test.txt" dev="dm-0" ino=35108539 scontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0


  62. Hash: vsftpd,ftpd_t,var_t,file,read

  63. # 3. 查看 /var/ftp 的 SELinux type
  64. [root@study ~]#  ll -Zd /var/ftp/
  65. drwxr-xr-x. root root system_u:object_r:public_content_t:s0 /var/ftp/
  66. [root@study ~]#  ll -Zd /srv/gogogo/
  67. drwxr-xr-x. root ftptest unconfined_u:object_r:var_t:s0   /srv/gogogo/

  68. # 4. 以 sealert 建议的方法来处理好 SELinux type
  69. [root@study ~]# semanage fcontext -a -t public_content_t '/srv/gogogo(/.*)?'
  70. [root@study ~]# restorecon -Rv /srv/gogogo
  71. restorecon reset /srv/gogogo context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:public_content_t:s0
  72. restorecon reset /srv/gogogo/test.txt context unconfined_u:object_r:var_t:s0->unconfined_u:object_r:public_content_t:s0
  73. # 再次访问就可以了
  74. [root@study ~]# curl ftp://ftptest:myftp123@localhost//srv/gogogo/test.txt
  75. test
複製代碼

   
在這個範例中,修改的是type,前一個範例中修改的是rule,不太一樣的

#無法變更FTP 聯機端口問題分析解決

比如你想要改變FTP 默認的啟動端口21 改成555,基本上,既然SELinux 的主體進程大多是被受限的網絡服務,很有可能連端口也限制了,下面嘗試修改端口,來查看是怎麼解決問題的

  1. # 1. 先处理 vsftpd 的配置文件,加入 port 的端口参数
  2. [root@study ~]# vim /etc/vsftpd/vsftpd.conf
  3. listen_port=555

  4. # 2. 重启服务,并查看日志
  5. [root@study ~]# systemctl restart vsftpd
  6. Job for vsftpd.service failed because the control process exited with error code. See "systemctl status vsftpd.service" and "journalctl -xe" for details.
  7. [root@study ~]# grep sealert /var/log/messages
  8. Mar 17 23:03:23 study setroubleshoot: SELinux is preventing /usr/sbin/vsftpd from name_bind access on the tcp_socket port 555. For complete SELinux messages run: sealert -l e3e3dee0-83eb-4cb8-b894-8be590fee082

  9. [root@study ~]# sealert -l e3e3dee0-83eb-4cb8-b894-8be590fee082
  10. SELinux is preventing /usr/sbin/vsftpd from name_bind access on the tcp_socket port 555.

  11. # 这个 92.2 的概率,基本上就是这个了
  12. *****  Plugin bind_ports (92.2 confidence) suggests   ************************

  13. If you want to allow /usr/sbin/vsftpd to bind to network port 555
  14. Then you need to modify the port type.
  15. Do
  16. # semanage port -a -t PORT_TYPE -p tcp 555
  17.     where PORT_TYPE is one of the following: certmaster_port_t, cluster_port_t, ephemeral_port_t, ftp_data_port_t, ftp_port_t, hadoop_datanode_port_t, hplip_port_t, isns_port_t, port_t, postgrey_port_t, unreserved_port_t.

  18. *****  Plugin catchall_boolean (7.83 confidence) suggests   ******************

  19. If you want to allow nis to enabled
  20. Then you must tell SELinux about this by enabling the 'nis_enabled' boolean.

  21. Do
  22. setsebool -P nis_enabled 1

  23. *****  Plugin catchall (1.41 confidence) suggests   **************************

  24. If you believe that vsftpd should be allowed name_bind access on the port 555 tcp_socket by default.
  25. Then you should report this as a bug.
  26. You can generate a local policy module to allow this access.
  27. Do
  28. allow this access for now by executing:
  29. # ausearch -c 'vsftpd' --raw | audit2allow -M my-vsftpd
  30. # semodule -i my-vsftpd.pp


  31. Additional Information:
  32. Source Context                system_u:system_r:ftpd_t:s0-s0:c0.c1023
  33. Target Context                system_u:object_r:hi_reserved_port_t:s0
  34. Target Objects                port 555 [ tcp_socket ]
  35. Source                        vsftpd
  36. Source Path                   /usr/sbin/vsftpd
  37. Port                          555
  38. Host                          study.centos.mrcode
  39. Source RPM Packages           vsftpd-3.0.2-25.el7.x86_64
  40. Target RPM Packages           
  41. Policy RPM                    selinux-policy-3.13.1-252.el7.noarch
  42. Selinux Enabled               True
  43. Policy Type                   targeted
  44. Enforcing Mode                Enforcing
  45. Host Name                     study.centos.mrcode
  46. Platform                      Linux study.centos.mrcode 3.10.0-1062.el7.x86_64
  47.                               #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64
  48. Alert Count                   1
  49. First Seen                    2020-03-17 23:03:20 CST
  50. Last Seen                     2020-03-17 23:03:20 CST
  51. Local ID                      e3e3dee0-83eb-4cb8-b894-8be590fee082

  52. Raw Audit Messages
  53. type=AVC msg=audit(1584457400.225:1008): avc:  denied  { name_bind } for  pid=11443 comm="vsftpd" src=555 scontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:hi_reserved_port_t:s0 tclass=tcp_socket permissive=0


  54. type=SYSCALL msg=audit(1584457400.225:1008): arch=x86_64 syscall=bind success=no exit=EACCES a0=4 a1=55e9e4d4e800 a2=1c a3=3 items=0 ppid=11440 pid=11443 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm=vsftpd exe=/usr/sbin/vsftpd subj=system_u:system_r:ftpd_t:s0-s0:c0.c1023 key=(null)

  55. Hash: vsftpd,ftpd_t,hi_reserved_port_t,tcp_socket,name_bind

  56. # 3. 根据建议解决执行指令, 92% 哪个指令下面 PORT_TYPE 下面又可选的 ftp_port_t
  57. # 但是笔者还是懵逼的,不知道为什么那么多里面就选这个了
  58. [root@study ~]# semanage port -a -t ftp_port_t -p tcp 555
  59. [root@study ~]# systemctl restart vsftpd
  60. [root@study ~]# netstat -tlnp
  61. Active Internet connections (only servers)
  62. Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name   
  63. tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1374/cupsd         
  64. tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1578/master         
  65. tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      2350/sshd: mrcode@p
  66. tcp        0      0 127.0.0.1:6011          0.0.0.0:*               LISTEN      10579/sshd: root@pt
  67. tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1/systemd           
  68. tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      1975/dnsmasq        
  69. tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1378/sshd           
  70. tcp6       0      0 ::1:631                 :::*                    LISTEN      1374/cupsd         
  71. tcp6       0      0 ::1:25                  :::*                    LISTEN      1578/master         
  72. tcp6       0      0 ::1:6010                :::*                    LISTEN      2350/sshd: mrcode@p
  73. tcp6       0      0 ::1:6011                :::*                    LISTEN      10579/sshd: root@pt
  74. tcp6       0      0 :::555                  :::*                    LISTEN      11573/vsftpd        
  75. tcp6       0      0 :::111                  :::*                    LISTEN      1/systemd           
  76. tcp6       0      0 :::22                   :::*                    LISTEN      1378/sshd     
  77. # 可以看到 vsftpd 的端口变成了 555 了

  78. # 4. 实验看看该 port 是否可用
  79. [root@study ~]# curl ftp://localhost:555
  80. drwxr-xr-x    2 0        0              42 Mar 17 09:03 pub
複製代碼

文章出處

 

臉書網友討論
*滑块验证:
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2024-4-26 01:41 , Processed in 0.053343 second(s), 25 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表