--- tags: 1091, lsa --- - Book mode https://hackmd.io/@ncnu-opensource/book Week 08(2020/11/12) === [TOC] # [防火牆](https://zh.wikipedia.org/wiki/%E9%98%B2%E7%81%AB%E5%A2%99) - 簡單:用來保護我們網路環境的東西 (ex. 可能會有惡意攻擊) - 廣義:透過規則來分析、過濾進出我們(管理的)網域的封包 - 在Linux中常用來設定防火牆規則的工具就是iptables - 機場比喻:封包傳遞流程圖 明白 ## iptables(Linux的封包過濾軟體) ### 流程 ![](https://i.imgur.com/tb38nNY.png) - 綠色 : table :::info - 封包: 人 - 防火牆(海關): 管理出入境的機制 ::: - 封包進入 : 飛機降落到台灣 - nat prerouting :將人群分流 - A(入境) : 目的地是台灣要入境的走上面這條 - fliter input 海關判斷進入可否(規定是客製化的) - 可 , 進台灣 - B(轉機): 目的地不是台灣要轉機的走旁邊那條 - filter forward 海關判斷轉機可否 - 可,去登機離開 - C(出境): 若要離開(出境流程) - nat output: 假設目的去日本要先知道去哪搭飛機(知道要去哪個機場) - filter output : 海關讓出否 - 可,去登機離開 ### 架構: tables表->chains 鍊->rules 規則 - 概念 - **table** (部門) - ex 負責引導的 nat 部門、過濾的 filter 部門 - **nat** : 引導路徑 - **filter** : 海關檢查判斷、能否轉機、能否出境 - **Chain**: (小組) - ex 過濾部門的處理小組 - INPUT: 讓不讓要入境的通過 - OUTPUT : 讓不讓要出境的通過 - **Rule**: (細節 assey or drop) - chain的 detail 規則 - ex : input - 來自疫情國家的不給進 - 來自歐洲的都給進 :::info - 一部門(Table) 有多小組(Chain) - 一小組(Chain) 有多規則細節(Rule) - table --> chain --> rule ::: ### 內容 | table | ==filter== | ==nat== | mangle | Raw | Security| | ----- | ----- | ---- | ---- | ---- | ---- | | chain | INPUT | PREROUTING | PREROUTING | PREROUTING | | | | OUTPUT | POSTROUTING| OUTPUT | OUTPUT| | | FORWARD| OUTPUT | FORWARD | | | | | | | INPUT | | | | | | | POSTROUTING | | | - table & chain: - ==**nat**== table: 讓封包知道下一步該往哪走(跟流向有關) - **PREROUTING** chain: - 要讓入境的封包知道==入境後==該怎麼走?或轉機的封包去哪裡轉機 - ex. 最終目的地是埔里,線抵達台灣,埔里怎麼去 - **POSTROUTING** chain: - 讓要出境的封包知道==出境後==該往哪走? - ex. 最終目的地是日本,現在人在飛機上,要飛往哪 - **OUTPUT** chain: - 讓在內部準備要出境的封包知道==該去哪個機場==才能出境 - ex. 最終目的地是日本,現在人在埔里,去哪個機場 - ==**filter**== table : 檢查封包能不能往那走( 跟過濾有關) - **INPUT** chain: - 讓不讓封包==入境== - ex. 現抵達台灣想要==去埔里==,海關,要不要放你進台灣 - **OUTPUT** chain: - 讓不讓封包==出境== - ex,現在我要離開台灣==去日本==,海關,能不能放我進日本 - **FORWARD** chain: - 讓不讓封包==轉機== - ex. 我從泰國來,目的要去日本 | prerouting | postrouting | output | | -------------- | -------------- | -------------------- | | 引導入境後走向 | 引導出去的走向 | 引導怎麼到出去的地方 | **下指令要看它在 terminal 要啥樣的table和chain在哪? ```shell= sudo iptables -nL --line-numbers sudo -t <想看的位置如nat> iptables -nL ``` - 因為我們沒有設定規則,所以沒有 : ) ^ _^合理 你為什麼要把我臉拆開 ![](https://i.imgur.com/vW3Fgbg.png) :::danger ```shell= sudo iptables -P INPUT DROP ``` 這行指令不要亂下!!很恐怖! (因為把所有 INPUT 都 DROP 掉,所以連你自己也進不去) ::: :::info - 大寫 `-P` 是`policy` - 小寫 `-p` 是`protocal` ::: :::danger 你沒有 `/etc/iptables/` 這個路徑是正常的,莫驚莫慌莫害怕 ::: **rule & target** ![](https://i.imgur.com/M3r8gHC.jpg) - **rule對象**(欄位解說)) - prot: 使用的封包協定,ex: tcp, udp, icmp - source : 針對**來源IP**進行限制 - detination: 針對『目標IP』進行限制 - **Target** :對對象進行的動作 - ACCEPT : 接收封包 - REJECT: 拒收封包 - DROP : 收完封包後丟掉 (對方不知道你有沒有收,不讀不回) - LOG : 紀錄這個封包,並將Log寫入檔案 `/var/log/message` - ex, log 再 drop - ==從上到下一行一行比對iptables適用的規則!!!== - **Policy**: - 若沒有一個符合,就會使用 policy (策略) - 預設策略 - eg. (policy ACCECPT) : 若沒有一個符合,就讓它通過 ### 流程 & 架構 ![](https://i.imgur.com/tb38nNY.png) - prerouting : 封包分流, 依照目的地 - filter : 判斷能否forward, input - nat : ### 指令操作 - ==查看==規則 ```shell= sudo iptables [-t Table] -nL # -n : 不進行 IP 與 HOSTNAME 的反查 # -L : 列出目前的 table 的規則 # -v : 列出更多的資訊,ex:通過該規則的封包總位元數、相關的網路介面等 ``` - 列出完整的防火牆規則,但是沒有規格化輸出 ```shell= iptables-save [-t Table] # -i lo : 由 lo 介面卡進來的封包 ``` ![](https://i.imgur.com/SFMuClk.png) - ==查看==規則,並以==行數==顯示 ```shell= sudo iptables -nL --line-number ``` ![](https://i.imgur.com/vvAoPFk.png) - ==新增==規則: - `-A`: append 新增加一條規則,該規則增加在原本規則的最後面 - `-I`: insert 配合 input chain 用,如果沒有指定此規則的順序,預設是插入變成第一條規則。 - ==清除==規則 - `-F`:清除所有iptable規則 - `-X`: 不會刪除預設chain - `-D` : 刪除特定規則 - ==修改==規則 - `-R`: 接chain名 & 行數 - 其他參數 - `-j` : 後面接動作,主要的動作有接受(ACCEPT)、丟棄(DROP)、拒絕(REJECT)及記錄(LOG) - ex: `sudo iptables -R INPUT 1 -j DROP` - `-p` : 協定 ex:udp、tcp、icmp - `--sport` : 限制來源端port number - `--dport` : 限制目標的port number(要進去的防火牆的port) - `-i` 設定in/out 網路介面 - `-i` : 封包所進入的那個網路介面,ex:eth0,lo。需與 INPUT 鏈配合 - `-o` : 封包所傳出的那個網路介面,需與 OUTPUT 鏈配合 ### 實做 ```shell= sudo iptables -P OUTPUT DROP ``` - 把FORWARD的policy改成DROP ```shell= sudo iptables -P FORWARD DROP ``` - 新增一條規則 ```shell= sudo iptables -A INPUT -i lo -j ACCEPT ``` ![](https://i.imgur.com/9F5scRr.png) - 刪除規則 ```shell= sudo iptables -D INPUT 1 ``` - 儲存設定檔 ```shell= sudo apt install iptables-persistent (choose no) ``` ``` sudo sh -c "iptables-save > /etc/iptables/rules.v4" sudo sh -c "ip6tables-save > /etc/iptables/rules.v6" cat /etc/iptables/rules.v4 cat /etc/iptables/rules.v6 ``` ![](https://i.imgur.com/nShd7Rh.png) ![](https://i.imgur.com/PpZnfsm.png) - 如果不小心按了yes(按YES不會怎樣) ```shell= sudo apt autoremove sudo apt purge iptables-persistent sudo apt install iptables-persistent ``` - 看自己的網段 ```shell= sudo ifconfig ``` ## Lab > 請大家有空先去下載 18.04 **server** 的 iso 檔 > 貼心的助教姐姐已經把下載網址貼在下面了,直接點擊就可以下載了喔ʕ•ᴥ•ʔ > [name=zinxin] [下載 18.04 iso 檔](https://www.ubuntu-tw.org/download/download.php?distro=server&version=18.04&arch=amd64) >不是下載在虛擬機裡面喔,是要準備灌新的虛擬機 ## 阻擋外部連線 - 擋掉外部透過網卡連到本機 - 本機的網卡(enp0s3) : inet 10.105.29.70 - 另一台 server 去執行 ping 10.105.29.70 會失敗 ```shell= sudo iptables -A INPUT -j DROP -i {網卡} ``` - 擋掉ssh ```shell= sudo iptables -A INPUT -j DROP -p tcp --dport 22 ``` - 擋掉ping ```shell= sudo iptables -A INPUT -j DROP -p icmp --icmp-type 8 ``` - 清除 iptables 的設定 ```shell= sudo iptables -F ``` ### ufw: ubuntu內建用來操作firewall的服務(方便設定iptables) - 不複雜的firewall(預設裝好) -> 法克剛剛不小心刪掉的 耶 ```shell= sudo service ufw status sudo ufw status sudo ufw enable (啟用ufw) # 拒絕接受這個來自這個 ip 的存取 sudo ufw deny from {ip} sudo ufw deny from ssh ``` ![](https://i.imgur.com/dGgFYcF.png) - 允許ssh存取 (預設好像會擋ssh) ```shell= sudo ufw allow ssh ``` ![](https://i.imgur.com/Fjq2rPy.png) ```shell= # 看規則編號 sudo ufw status numbered ``` ![](https://i.imgur.com/iCyVoWQ.png =500x) ```shell= sudo ufw delete 1 ``` ### Uif(需透過設定檔) Userfriendly Iptables Frontend - uif = 便於設定的 iptables 界面 - uif精神: 所有設定都要定義**代稱**,不能直接打上 IP。 - 下載: ```shell= sudo apt install uif ``` - 在目錄`/etc/uif` 下的 `uif-ipv4-networks.inc` 中定義代稱: ```shell= sudo vim /etc/uif/uif-ipv4-networks.inc ``` - 定義代稱 `badbad`對應的`{ip}` ![](https://i.imgur.com/ILl1x6I.png =400x) - 在主要設定檔`uif.conf` ,新增剛剛定義的代稱 `badbad` 對應的條件 - **所有要過濾的條件都在`filter`中** - `+`:要、允許 - `-`:不要、不允許 - `loop`:對應本機的網卡`lo` ```shell= //從上到下依序讀 filter{ in+ i=loop s=localhost out+ o=loop d=localhost } //in: input //out: output //s: source //d: destination ``` - 最下方加上 `in- s=badbad` - ![](https://i.imgur.com/PIFRdHh.png) - 將剛剛的設定吃進去 - `-c`: 指定檔案 ```shell= sudo uif -c /etc/uif/uif.conf ``` ## Prepare to start - 新增主機介面卡 ![](https://i.imgur.com/Vjz9nVp.png) - firewall (server版) - 網卡1: bridge 橋接介面卡 ![](https://i.imgur.com/TXURXuQ.png) - 網卡2: 連接 student ![](https://i.imgur.com/OsgoITU.png) - 網卡3: 連接 http ![](https://i.imgur.com/MW79XbQ.png) - student (server版) - ~~NAT 網路~~ / 主機介面卡 - 無法連到外網 ![](https://i.imgur.com/dsDqmm8.png) - http-server (server版) - ~~NAT 網路~~ / 主機介面卡 - 無法連到外網 ![](https://i.imgur.com/Qv4QJRi.png) ## DMZ ![](https://i.imgur.com/a4mos9R.jpg) ### LAB ### 設定firewall 的iptables - 將規則清乾淨 - `-X`: 清掉chain ```shell= sudo iptables -F #清空一些客製的chain sudo iptables -X # 要把東西都先開啟 sudo iptables -P INPUT ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -P FORWARD ACCEPT ``` :::success **需求** - firewall - 對外網卡 *1 (橋接介面卡, bridge) - 對內網卡 *2 (僅限主機介面卡, Host-Only) - http-service - 對內網卡 *1 (僅限主機介面卡, Host-Only) - student - 對內網卡 *1 (僅限主機介面卡, Host-Only) ::: **ACCEPT 已建立連線的連線(ESTABLISHED)、相關的連線的 Forward** ```shell= sudo iptables -A FORWARD \ -m comment --comment "established traffic" \ -j ACCEPT \ -m conntrack --ctstate "ESTABLISHED,RELATED" ``` > 當連線狀態: ESTABLISHED,RELATED 就Accept > `-m conntrack --ctstate`: 比對連線狀態 ![](https://i.imgur.com/XWQziaj.png) **ACCEPT 從內網段(lan)來,目的地是外網段的 FORWARD** ```shell= sudo iptables -A FORWARD -j ACCEPT -i {lan} -o {wan} \ -m comment --comment "allow outbound traffic from lan" ``` - 將`{lan}`改成網卡名稱(內網的) - 將`{wan}`改成網卡名稱(外網的) **要出去的流量先做 MASQUERADE** `因為內網的 IP 外網看不懂` `MASQUERADE: 將內網IP轉成外網IP` ```shell= sudo iptables -t nat \ -A POSTROUTING -o {wan} -j MASQUERADE \ -m comment --comment "masquerade lan -> wan" ``` - `sudo iptables -t nat -nvL`: masquerade是建在`nat封包對應表`這張表,故要去 `nat` 查看 - `-t` :指定說去看`nat`表 - `-nvL`: 多個`v` 顯示更詳細 - 可看到`in (進來)`的網卡 及 `out 出去`的網卡名稱 - `sudo iptables -nL` (預設在filter table = `sudo iptables -t filter -nL`) - 若iptables的規則重複 ```shell= # 顯示規則的行數 sudo iptables -t nat -nL --line-numbers # 假設是在POSTROUTING chain多了一條規則,查看是第幾行後(假設是2) -D 刪掉 sudo iptables -t nat -D POSTROUTING 2 ``` **開啟firewall幫忙轉送的功能 (1) forward** ```shell= sudo vim /etc/sysctl.conf ``` ![](https://i.imgur.com/gk9eaye.png) >拿掉註解 **檢查是否開啟 (顯示 net.ipv4.ip_forward = 1)** ```shell= sudo sysctl -p ``` - 如果顯示 1 就是成功開啟了 ### **set firewall as Gateway**: 於`LAN 的虛擬機上`設定 `gatewayID == firewall 與 LAN 同網段 IP` - 將 firewall 當成 LAN 要出去的 gateway - 當你在LAN要送東西出去,就直接先轉到firewall ```shell= sudo route add default gw {firewall IP} # {firewall IP} 是和student連的那個內網IP喔 ``` - 查看 gateway 狀態 ```shell= route -n ``` ![](https://i.imgur.com/PtqxUra.png) > IP為自己內網的IP - 試著ping外網: `ping 8.8.8.8` - 設定完後,應能往外ping了 ### **在LAN虛擬機上 增加 DNS設定 (option)**: :::danger 怎麼進去的 => 至LAN虛擬機 ::: :::warning 若使用 domain name 無法上網 ( `ping www.google.com` 無回應的話 ) 請去 `/etc/resolv.conf` 更改 DNS 伺服器位置 (導到Google) 可多設幾台(ex: cloudflare) 避免找不到 ```shell= # nameserver 127.0.0.53 # options edns0 #google的 nameserver 8.8.8.8 #cloudflare的 nameservr 1.1.1.1 ``` ::: ## 如果 firewall 只有兩張網卡 ```shell= sudo vim /etc/netplan/00-installer-config.yaml ``` - 手動開網卡 - 網卡名稱去 `ip a` 看 ```shell= 網卡名稱: dhcp4:true ``` ![](https://i.imgur.com/NGpJLtz.png) - 上面手動設定好後 ```shell= # 確認有沒有問題 sudo netplan try # 啟動 sudo netplan apply ``` ### 另一個方式開網卡的方式: 1. 下載 `ifupdown`: ```shell= sudo apt install ifupdown ``` 2. 至`/etc/network/interfaces` 中設定: ```shell= sudo vim /etc/network/interfaces ``` 3. 設定網卡,啟用DHCP: (有幾張有幾張網卡要啟用 就打幾次) ```shell= auto {網卡名稱} iface {網卡名稱} inet dhcp #example: auto enp0s8 iface enp0s8 inet dhcp ``` 4. 啟用指定的網卡名 (需是有在interfaces中設定的網卡) ```shell= sudo ifup {網卡名} ``` ## Nginx - load balance(==會考喔==) - 將工作分給多台server,分擔工作量 - 當有許多人要求服務時,可避免負荷太重 ![](https://i.imgur.com/gRZeolj.jpg =600x) - 於 `/etc/nginx/sites-available`建config檔: `sudo vim lab-work` > 別再打成li了 ```shell= upstream backend { server localhost:8081; server localhost:8082; } server { listen 8080; server_name works.lab.com; location / { proxy_pass http://backend; } } ``` - 利用 upstream模組 導流到 backend中的 `apache2` `lighttpd`(port號 看自己設定多少) - 在`/etc/hosts` 中加入 `127.0.0.1 works.lab.com` ```shell= sudo ln -s /etc/nginx/sites-available/lab-work ../sites-enabled/ sudo nginx -t # 檢查是否成功 sudo service nginx reload ``` [可愛的聊天室](https://app.sli.do/event/cq4nrsrz) ## 課後補充 ### 常見問題 :::info **問題描述** upstream 導給兩台 server,但 reload 網頁測試的時候發現永遠只有一個頁面出現 ::: 可能原因查找與解法 1. 瀏覽器 Cache 沒清 - 解法:與 [Shift] 組合技 - ex: [Ctrl][R] + [Shift] 2. upstream 設定的 server 其中一台不能運行 - 偵錯 - 測試 upstream 的兩串 server 網址能否取得正確網頁內容 - `sudo netstat -ntupl` 確認需要的服務有沒有正確開啟、監聽哪個 port - 解法: 將 upstream server 設定成服務實際監聽的 port - ex:apache 實際監聽 8091,則改成 server localhost:8091 ### [補充] nginx upstream 的不同演算法設定 :::success 在 Nginx 中 load balance 是使用 upstream 模組所完成 將 HTTP 的流量導向在 upstream 中所設定的一群 server 們 導流會基於指定不同的**演算法**,以不同的方式分流 在 nginx 中當沒有指定演算法的時候(如上課 lab) 是預設以 Round Robin 進行分流 除此之外 Nginx 還定義了其他的演算法 下面將列舉幾個常見演算法,與說明分流方式的不同 ::: - `Round Robin` - nginx 預設演算法(沒有設定時) - **平均**分流給 server 群 - 如課程 lab 範例 - `Least Connections` - 當前**連線數最少** server - 使用`least_conn` ```s= upstream backend { least_conn; server backend1.example.com; server backend2.example.com; } ``` - `IP Hash` - 根據 request **IP 的 hash 值**做分配 - 可以保證同一個 IP 會導回同一台伺服器 - 使用`ip_hash` ```s= upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; } ``` ### Setting of network (有關網卡差別與補充) > 有任何問題歡迎在群組上面提問<br/> > 這邊的 Host / Host OS 是指實體主機(EX: 在 Windows 上開 VM 時,Host 是指 Windows) > [name=芷欣] ![](https://i.imgur.com/IIQjWrV.png) #### NAT、NAT 網路 1. 預設的網路模式 2. 最簡單的方式,Host OS 能上網,Guest OS 就能上網 3. 會取得 Private IP 4. VM 間無法 ping 5. VM 可以 ping Host(ping VM 的 gateway 就是 ping Host) 6. Host 不能 ping VM 7. 原理 - 虛擬機的請求傳遞给 NAT Engine,由它來利用 Host 進行對外的網路訪問,返回的數據包再由 NAT Engine 给虛擬機 - VM 通過 Host 連線到外網,由主機轉送封包 - `NAT` 官方文件[節錄] :::info Network Address Translation Network Address Translation (NAT) is the simplest way of accessing an external network from a virtual machine. Usually, **it does not require any configuration on the host network and guest system**. For this reason, it is the **default** networking mode in VirtualBox. ::: - `NAT 網路` 官方文件[節錄] :::info The Network Address Translation (NAT) service works in a similar way to a home router, grouping the systems using it into a network and preventing systems outside of this network from directly accessing systems inside it, but letting systems inside communicate with each other and with systems outside using TCP and UDP over IPv4 and IPv6. ::: #### 橋接網路卡 Bridge 1. Host 可以上網,VM 就可以上網 2. VM 之間可以互 ping 3. VM 與 Host 間可以互 ping 4. IP: - 與 Host 在同一網段 - gateway 會與主機相同 5. 原理 - 通過 Host 網卡,架設一條橋,直接連入到網路中。它使得虛擬機器能被分配到一個網路中獨立的 IP,所有網路功能完全和在網路中的實體機器一樣 (虛擬機是通過 Host 所在網路中的 DHCP 服務得到 IP,所以按理來說,兩者是完全獨立的,但事實卻是虛擬機是沒有獨立硬體的,它還是要依靠主機的網卡,因此實體主機要斷開網路,虛擬機器也就沒法拿到 IP) - `橋接網路卡` 官方文件[節錄] :::info With bridged networking, Oracle VM VirtualBox uses a device driver on your host system that filters data from your physical network adapter. This driver is therefore called a **net filter** driver. This enables Oracle VM VirtualBox to intercept data from the physical network and inject data into it, effectively creating a new network interface in software. When a guest is using such a new software interface, it looks to the host system as though the guest were physically connected to the interface using a network cable. The host can send data to the guest through that interface and receive data from it. This means that you can set up routing or bridging between the guest and the rest of your network. ::: #### 僅限主機介面卡、Host-only Adapter模式(Host-only networking) 1. Guest OS 上網方式跟 Host OS 一樣 2. VM 不能上網 3. VM 間可以互 ping 4. VM 可以 ping 到 Host 5. 原理 - 通過 VirtualBox Host-Only Network 網卡進行連接,虛擬機器以此 IP 作為 gateway,因此模擬了一個本機與各個虛擬機的區域網路 - `Host-Only Networking` 官方文件[節錄] :::info Host-only networking is another networking mode that was added with version 2.2 of VirtualBox. It can be thought of as a **hybrid between the bridged and internal networking modes**: as with bridged networking, the virtual machines can talk to each other and the host as if they were connected through a physical Ethernet switch. Similarly, as with internal networking however, a physical networking interface need not be present, and the virtual machines cannot talk to the world outside the host since they are not connected to a physical networking interface. ::: #### Reference - [官方文件- chapter6. Virtual Networking](https://www.virtualbox.org/manual/UserManual.html#network_nat) - [ORACLE VM VIRTUALBOX 網路設定與網卡說明](http://arbitrarytsai.blogspot.com/2019/05/from-httpskanchengzxdfgcv.html) #### 橋接介面卡無法ping到外網的解決方式 :::info 1. 換個網路 2. 重新啟動網卡軟體: [點我看流程](https://blog.jia543.com/2018/08/virtualbox.html) :::