---
# System prepended metadata

title: NASA HW11 Nginx

---

# NASA HW11 Nginx
* 鍾詠傑
* 41173058h
## ref

[YT_nginx教學](https://www.youtube.com/watch?v=sCJcusORiE8&t=1148s&ab_channel=GeekHour)

[LAB12](https://docs.google.com/presentation/d/16Q5su-g1GEwy22G1oVWPOsLCznFL7tukNteNB9JOPUE/edit?usp=sharing)
[ref](https://ithelp.ithome.com.tw/m/articles/10267249)
[ref](https://ithelp.ithome.com.tw/m/articles/10267249)
[ref](https://zh.wikipedia.org/zh-tw/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8)
[ref](https://www.cloudflare.com/zh-tw/learning/cdn/glossary/reverse-proxy/)
[ref](https://wiki.debian.org/Nginx/DirectoryStructure)
[ref](https://www.quora.com/What-is-a-CA-PKI-and-TLS-in-internet-security)
[REF](https://aws.amazon.com/tw/what-is/ssl-certificate/)
[ref](https://stackoverflow.com/questions/10674867/nginx-default-public-www-location)

<div style="page-break-after:always;"></div>

## 1
### 1. Apache 和 Nginx 為常被使用的網頁伺服器。請比較兩者之間的差異，至少列出三點。(5%)


| 功能           | Apache                      | Nginx                            |
|----------------|-----------------------------|----------------------------------|
| 資源消耗         | 較多記憶體及 <br>CPU 資源      | 較少記憶體及 <br>CPU 資源                |
| 處理請求速度      | 較慢，<br>尤其在高流量下        | 較快，<br>尤其在高流量下                |
| 配置           | 使用簡單的<br>文本配置檔案            | 使用更直觀且<br>模組化的配置方式          |
| 事件驅動         | 較少的事件驅動機制               | 使用非阻塞事件驅動架構               |
| 處理靜態內容      | 效能稍低，<br>尤其在大型檔案或高流量下     | 效能高，<br>能夠處理大量靜態內容          |
| 處理動態內容      | 較為複雜，<br>但支援多種語言和技術        | 通常需要額外的<br>模組或中介軟體來處理     |
| 配置檔案讀取      | 需要重新啟動伺服器<br>才能應用配置變更     | 可以動態地重新載入配置，無需重新啟動伺服器 |


<div style="page-break-after:always;"></div>

### 2. 請解釋 Static Web Server 和 Dynamic Web Server，以及他們之間的差異。(5%)


| 特徵                  | Static Web Server                 | Dynamic Web Server               |
|----------------------|----------------------------------|----------------------------------|
| 內容                | 提供靜態內容，如<br>HTML、CSS、JavaScript 檔案等  | 提供動態生成的內容，<br>例如從資料庫擷取的內容、<br>使用者註冊資訊等  |
| 產生方式            | 內容在伺服器上<br>預先產生並存儲為檔案         | 內容在每次請求時<br>根據特定邏輯和資料動態生成  |
| 適用性                | 適用於不經常變化或變化緩慢的內容<br>，如企業網站、部落格等 | 適用於需要即時更新的內容<br>，如社交媒體平台、<br>電子商務網站等  |
| 負載                | 較輕，因為內容是<br>預先生成的並直接提供       | 較重，因為每次請求<br>都需要動態生成內容      |
| 技術和<br>語言選擇           | 不需要特定的後端技術，<br>可以使用純靜態技術<br>（如 HTML、CSS、JavaScript） | 需後端技術和<br>資料庫來動態生成內容<br>，可以使用各種語言和框架<br>（如 PHP、Python、Node.js） |
| 快取和<br>效能              | 靜態內容易於快取<br>，並且效能較高            | 動態內容通常不易於快取<br>，且效能較低       |
| 負載均衡               | 不需要負載均衡<br>，因為內容是靜態的            | 可能需要負載均衡，以平衡<br>伺服器上的動態內容生成請求 |


<div style="page-break-after:always;"></div>

### 3. 承上題，請介紹 CSR、SSR、SSG、ISR 四種網頁渲染模式與各自 1 個優點。(5%)

#### Static Site Generation (SSG)
SSG 或是靜態生成就是 build 整個專案的時候產生 HTML 檔案，這些 HTML 檔案已經包含所需要顯示的資料。這渲染模式是預渲染 (pre-rendering) 的一種。SSG 很適合做內容不會有變化的靜態網站，因為所有資料是 build 時得到的。這些 HTML 檔案可以放在 CDN 上然後被 cache 而提升網站效能，除了這點之外，採用 SSG 渲染模式也利於 SEO。

#### Server-side Rendering (SSR)
SSR 或是伺服器端渲染意思是每次瀏覽器 (客戶端 / client-side) 發送請求 (request) 時，伺服器才會產生 HTML 檔案然後丟回瀏覽器顯示。這渲染模式很適合變化頻率高的資料。不過因為伺服器需要時間產生 HTML 檔案，所以網站回應時間會比較久，使用者等待時會看到白畫面。SSR 也算是預渲染的一種，所以對 SEO 也較友善。可是該注意，這方式需要伺服器一直處理使用者的請求。

#### Client-side Rendering (CSR)
CSR 或是客戶端渲染跟名字差不多的意思，伺服器傳給瀏覽器的 HTML 檔案可以算是無內容的。瀏覽器跟伺服器拿完資料才能渲染在畫面上。SPA (Single Page Application 像 React 或 Vue) 使用的渲染模式就是 CSR。這模式的最大優點是切換頁面的時候不需要再跟伺服器拿檔案，使用者不會看到白畫面了，算是很好的使用者體驗。不過渲染時間會依賴客戶端的環境，也因為這樣，伺服器的負擔降低不少。

#### Incremental Static Regeneration (ISR)
ISR 或是增量靜態生成比較少聽到的渲染模式，也算是預渲染的一種。ISR 在 build 專案時產生所有 (或部份) HTML 檔案，等到有新的 request 而且已經過了預定的時間，伺服器會先給瀏覽器舊檔案而在背後重新產生最新檔案，產生完之後再丟給瀏覽器做顯示。如果使用者到了一個還沒被 generate (產生) 的頁面，伺服器將當下產生該檔案也會做 cache，所以下一個到這頁面的使用者可以直接拿到 cache 裡的檔案。 ISR 很像 SSG 不過它解決了 SSG 不能更新資料內容的問題，而且 HTML 檔案也會被 cache 在 CDN 上，所以也減輕 SSR 對伺服器的負擔。


* 資料不斷地變化而且不需要 SEO 的內部系統 dashboard 很適合用 CSR，
* 資料變化率不低可是需要 SEO，可以考慮用 SSR，
* 資料幾乎不用更新像活動或行銷網站，SEO 也很重要，用 SSG 很適合，
* 資料不太需要更新或是有太多頁面而且需要 SEO 例如商品頁，那 ISR 就是個好選擇。

[ref](https://ithelp.ithome.com.tw/m/articles/10267249)

<div style="page-break-after:always;"></div>

### 4. Proxy 是網路伺服器常用的技術。請解釋 Proxy，並列出三項使用 Proxy 的好處 (功能)。(5%)
什麼是代理伺服器？
正向代理（通常稱為代理、代理伺服器或 Web 代理）是位於一組用戶端機器前方的伺服器。當這些電腦向網際網路上的網站和服務發出請求時，代理伺服器會攔截這些請求，然後代表這些用戶端與網頁伺服器進行通訊，就像中間人一樣。

1. 提高訪問速度
    通常代理伺服器都設定一個較大的緩衝區，當有外界的資訊通過時，同時也將其儲存到緩衝區中，當其他使用者再訪問相同的資訊時， 則直接由緩衝區中取出資訊，傳給使用者，以提高訪問速度。
1. 控制對內部資源的訪問
    如某大學FTP（前提是該代理位址在該資源的允許訪問範圍之內），使用教育網內位址段免費代理伺服器，就可以用於對教育網開放的各類FTP下載上傳，以及各類資料查詢共享等服務。
1. 過濾內容
    例如限制對特定電腦的訪問，將一種語言的資料翻譯成另一種語言[需要解釋]，或是防禦代理伺服器兩邊的攻擊性訪問。
1. 隱藏真實IP
    上網者也可以通過代理伺服器隱藏自己的IP，但是只一個代理很難保證安全，更安全的方法是利用特定的工具建立代理鏈（如：Tor）。
1. 突破網站的區域限制
    通過代理伺服器訪問Netflix、Google等對中國地區進行內容限制（如防火長城）的網站；非中國大陸使用者也可通過代理伺服器訪問愛奇藝等著作權僅授予中國大陸地區的網站。


[ref](https://zh.wikipedia.org/zh-tw/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8)

<div style="page-break-after:always;"></div>

### 5. 承上題，請解釋 Reverse proxy，以及列出三項使用 Reverse Proxy 的好處 (功能)。（5%）
什麼是反向代理？
反向代理是位於網頁伺服器前方的伺服器，並將用戶端（例如 Web 瀏覽器）要求轉送至那些網頁伺服器。反向代理通常在實作時有助於增加安全性、效能及可靠性。為了更好地瞭解反向代理的運作原理及其提供的好處，我們先來定義一下什麼是代理伺服器。

反向代理是位於一個或多個網頁伺服器前方的伺服器，用於攔截來自用戶端的請求。這與正向代理不同，在正向代理中，代理位於用戶端前方。使用反向代理，當用戶端向網站的原始伺服器傳送請求時，反向代理伺服器會在網路邊緣攔截這些請求。然後，反向代理伺服器將向原始伺服器傳送請求並從原始伺服器接收回應。

正向和反向代理之間的區別很微妙，但很重要。簡單來說，正向代理位於用戶端前方，並確保沒有原始伺服器直接與該特定用戶端通訊。而反向代理位於原始伺服器前方，並確保沒有用戶端直接與該原始伺服器通訊。

1. 負載平衡：
    - 每天獲得數百萬使用者的熱門網站可能無法使用單個原始伺服器處理其所有傳入網站流量。相反，網站可以分散在不同伺服器集區中，所有伺服器都處理同一網站的請求。在這種情況下，反向代理可以提供負載平衡解決方案，該解決方案將在不同的伺服器之間均勻分配傳入流量，以防止任何單個伺服器過載。如果伺服器完全出現故障，其他伺服器可以代為處理流量。
3. 防止攻擊：
    - 使用反向代理后，網站或服務永遠不需要顯示其原始伺服器的 IP 位址。這使得攻擊者更難利用針對性攻擊，例如 DDoS攻擊。相反，攻擊者只能針對反向代理（如 Cloudflare的 CDN），後者將具有更嚴格的安全性和更多的資源來抵禦網路攻擊。全球伺服器負載平衡 (GSLB)：在這種負載平衡形式中，網站可以分散在全球的多台伺服器上，反向代理會將用戶端請求傳送到地理位置上離它們最近的伺服器。這減少了請求和回應需要傳輸的距離，從而最大限度地減少載入時間。
4. 快取：
    - 反向代理還可以快取內容，從而提高效能。例如，如果巴黎的使用者造訪網頁伺服器位於洛杉磯的反向代理網站，則該使用者實際上可能連接到巴黎的本地反向代理伺服器，然後該伺服器需要與洛杉磯的原始伺服器通訊。然後，代理伺服器可以快取（或臨時儲存）回應資料。後面瀏覽該網站的巴黎使用者將從位於巴黎的反向代理伺服器獲取本地快取版本，從而提高效能。
5. SSL 加密：
    - 為每個用戶端加密和解密 SSL（或 TLS）通訊對於原始伺服器來說計算量很大。可以將反向代理設定為解密所有傳入請求並加密所有傳出回應，從而釋放原始伺服器上的寶貴資源。

[ref](https://www.cloudflare.com/zh-tw/learning/cdn/glossary/reverse-proxy/)

<div style="page-break-after:always;"></div>

## Web Server Configurations (45%)
• 請完成接下來的題目，並將你作答的指令/修改部分完整記錄在 report 中。另外，8, 9, 10, 11,12 題完成後請截圖瀏覽器畫面，要包含網址的部分。

### 6. Basic Setups (5%)

• 請在任意一台工作站 (ws[x].csie.ntu.edu.tw) 上，使用 /tmp2/nasa-hw11/debian.iso 自行安
裝一個 Debian 12.5.0 的 VM，並將 username 設為你的學號 (ex: b12902000)
• 為了接下來操作方便，請將該 user 加入 sudoers file
• 請使用 HW5 時用過的 NAT port forwarding 方法，將工作站的兩個 port 分別 forward 到 VM 的 http 及 https port，以便之後連上服務。
• 請安裝 Nginx server 所需的相關套件，並啟動 Nginx Service。

```
qemu-img create -f qcow2 -o cluster_size=2M debian.qcow2 30G
```
```=
virt-install --name=G36HW11 \
--vcpus=4 --memory=8192 \
--disk path=/tmp2/41173058h/hw11/debian.qcow2,size=30 \
--os-variant=debian12 --cdrom=debian.iso \
--network=default \
--console pty,target_type=serial \
--graphics vnc,listen=0.0.0.0,password=0910  \
--noautoconsole

```
virsh 重設指令:
```=
virsh shutdown G36HW11
virsh destroy G36HW11
virsh undefine G36HW11 --remove-all-storage
```

VM:

![image](https://hackmd.io/_uploads/r1DaZWpGC.png)

NAT port forwarding :

```=
virsh qemu-monitor-command --hmp G36HW11 'hostfwd_add ::3622-:22'
virsh qemu-monitor-command --hmp G36HW11 'hostfwd_add ::3680-:80'
virsh qemu-monitor-command --hmp G36HW11 'hostfwd_add ::36443-:443'
```
 ![image](https://hackmd.io/_uploads/B1iXT-CMR.png)
 
安裝並啟用 nginx (如同lab12)

<div style="page-break-after:always;"></div>

### 7. Firewall Settings (5%)

• 為了能讓伺服器正常運作且安全無虞，我們需要限制能連線到 VM 的 TCP/IP port 只有 22, 80, 及 443。請利用任意一種 linux 套件/指令設定你的 VM 的防火牆，使其符合以上規則。另外請附上你如何測試防火牆是正常運作的。

```=
apt-get install ufw

sudo ufw default deny incoming  # 默認拒絕所有入站連接
sudo ufw default allow outgoing # 允許所有出站連接
sudo ufw allow 22/tcp           # 允許SSH端口
sudo ufw allow 80/tcp           # 允許HTTP端口
sudo ufw allow 443/tcp          # 允許HTTPS端口

sudo ufw enable
```

![image](https://hackmd.io/_uploads/ry0MSzRzR.png)


<div style="page-break-after:always;"></div>

### 8. The Main Page (5%)

• 當我們在你的本機瀏覽器連上 http://{your_vm_ip} 時，應該要會出現顯示 Welcome to
nginx! 的預設畫面。我們希望能夠顯示 index.html 的內容：Hello! My name is {your_id}!。
• html file 的內容部分，能夠顯示要求字樣即可。

```=
sudo vim /var/www/html/index.html
sudo systemctl reload nginx
```


![image](https://hackmd.io/_uploads/H1CXKGCMC.png)

<div style="page-break-after:always;"></div>

### 9. User Directory (5%)

• CSIE 工作站上，每個使用者的 home directory 中都有一個 htdocs 資料夾，只要在資料
夾中放下 index.html，連上 https://www.csie.ntu.edu.tw/~username 即可以看到 index.html 的內容。
• 請設定你的 Nginx Server ，使其可以達到與工作站相同的功能：當連上 http://{your_vm_ip}/~{username}/ 時，可以顯示你的家目錄 htdocs 裡面的 index.html，並顯示出Hello! My name is {your_id}!
• 不用建立一個新的 user，只要能用上述的 url 連上並顯示內容即可。
• html file 的內容部分，能夠顯示要求字樣即可。

```
sudo vim /etc/nginx/sites-available/default
```

```=
location /~h41173058/ {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                alias /home/h41173058/htdocs/;
                index index.html;
                #try_files $uri $uri/ =404;
        }
```
```
sudo chmod -R 755 /home/h41173058/
```

<div style="page-break-after:always;"></div>

這裡也可以透過regex 來對別的 homepage 進行自動載入

```=
location ~ ^\/~([\w]+)\/(.*)$ {
    alias /home/$1/htdocs/;
    index index.html;
    try_files $2 $2/ =404;
}
設定中 location ~ 會
```

編輯完後要設定資料夾及檔案權限使得 `nginx` 可以存取到檔案
`chmod 755 /home/{user_dir}` (不建議在一般環境這樣做)
正確的做法是分配好`nginx`的瀏覽權限

[ref](https://wiki.debian.org/Nginx/DirectoryStructure)

[ref](https://stackoverflow.com/questions/10674867/nginx-default-public-www-location)

![image](https://hackmd.io/_uploads/HywTUwRMA.png)


<div style="page-break-after:always;"></div>

### 10. Secret (5%)

• 我們想在 Nginx Server 上放一個秘密檔案 secret.html，並且只讓 192.168.28.0/24 中的 ip
access（透過連上 http://{your_vm_ip}/secret.html)。
• html file 的內容部分，可以發揮創意。

添加設置：在Nginx的配置文件中，您需要添加一個location區塊，以限制對secret.html文件的訪問。在此location區塊中，使用allow和deny指令來限制IP訪問。確保替換192.168.28.0/24為您想要允許訪問的IP範圍。

```=
server {
    ...
    location /secret.html {
        allow 192.168.28.0/24;
        deny all;
    }
    ...
}
```

![image](https://hackmd.io/_uploads/rJ80g4AGR.png)

<div style="page-break-after:always;"></div>

### 11. Log (5%)

• 由於網頁服務有遭受惡意攻擊的可能性，因此我們想要紀錄下服務的 access log。
• 請適當 access 你的服務，產生紀錄後截圖 access log 的內容。

```
sudo vim /etc/nginx/nginx.conf
```
新增此行
```=
http {
    ...
    access_log /var/log/nginx/access.log;
    ...
}

```
```
cat /var/log/nginx/access.log
```

![image](https://hackmd.io/_uploads/BkS_XEAz0.png)

<div style="page-break-after:always;"></div>

### 12. OpenSSL (25%)

#### (a) 請解釋：PKI 和 TLS 有什麼關聯？(2%)
#### (b) 請解釋憑證跟 CA 之間的關係 (3%)


Public Key Infrastructure (PKI) is a set of processes, policies and technology for associating cryptographic keys with the entity to whom those keys were issued. It is a well-known authentication and encryption method used in internet banking and e-commerce to confirm the identity of trading partners as well as validate information being shared. PKI is made of several elements which are:
公鑰基礎設施 (PKI) 是一組流程、策略和技術，用於將加密金鑰與向其頒發這些金鑰的實體相關聯。它是網路銀行和電子商務中使用的一種眾所周知的身份驗證和加密方法，用於確認貿易夥伴的身份以及驗證共享資訊。 PKI 由以下幾個元素組成：

- Certification Authority (CA) - A trusted entity that serves authentication infrastructures as well as registering entities that need PKI. It is the organization that issues out digital certificates. Examples of Certification Authorities include: Comodo, Verizon, GoDaddy and so on.
憑證授權單位 (CA) - 為身分驗證基礎設施提供服務以及註冊需要 PKI 的實體的受信任實體。頒發數位證書的組織。認證機構的例子包括：Comodo、Verizon、GoDaddy 等。

- Registration Authority (RA) - is certified by a root CA and validates the identity of users requesting information on the certificate authority.
註冊機構 (RA) - 由根 CA 進行認證，並驗證要求憑證機構資訊的使用者的身分。

- Certificate Revocation List (CRL) - Provides a means for checking the continued validity of the certificates for which the certification authority (CA) has responsibility. The CRL details digital certificates that are no longer valid.
憑證撤銷清單 (CRL) - 提供一種方法來檢查憑證授權單位 (CA) 負責的憑證的持續有效性。 CRL 詳細說明了不再有效的數位憑證。

- Certification Practice Statement (CPS) - Is a set of rules governing the CA’s operations. It provides an understanding of the value and trustworthiness of certificates issued by a given CA.
認證實務聲明 (CPS) - 是一套管理 CA 營運的規則。它提供了對給定 CA 頒發的證書的價值和可信度的理解。

- Transport Layer Security (TLS) and its predecessor Secure Socket Layer (SSL) is an Internet protocol that is intended to provide security over the internet. TLS uses PKI certificates to authenticate parties communicating with each other as well as encrypting the communication session.
傳輸層安全性 (TLS) 及其前身安全通訊端層 (SSL) 是一種 Internet 協議，旨在透過 Internet 提供安全性。 TLS 使用 PKI 憑證來驗證相互通訊的各方並加密通訊會話。


In summary TLS uses PKI to secure information over the internet. However, it is important to note that TLS supports other encryption standards which are not part of PKI.
總之，TLS 使用 PKI 來保護網路上的資訊。但是，值得注意的是，TLS 支援不屬於 PKI 的其他加密標準。

[ref](https://www.quora.com/What-is-a-CA-PKI-and-TLS-in-internet-security)
[REF](https://aws.amazon.com/tw/what-is/ssl-certificate/)

<div style="page-break-after:always;"></div>

#### (c) 請使用 OpenSSL 自行簽署一個 root CA，再用此 CA 簽署一張憑證供你的 server 使用，使你可以使用 https 連上你的服務。(20%)
• 請詳細記錄你使用的指令或修改，並截圖你的 server 已經可以使用 https 傳輸。(P.S.
根據你所使用的瀏覽器，你可能會需要額外查詢如何讓瀏覽器信任特定 CA 以達成題
目要求）
• 請使用 openssl x509 -in [certificate.crt] -text -noout 指令輸出你的 root CA 及 server
的 crt 檔並截圖。

我這裡也可以使用修改後合併的單行命令來同時生成

產生 CA 的金鑰與自簽憑證。
```
openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt
```
產生網站的金鑰與 Certificate Request，其中 Certificate Request 的 Common Name 是網站的域名。
```
openssl genrsa -out site.key 2048
openssl req -new -key site.key -out site.csr
```
然後使用 CA 的私鑰與憑證幫剛剛的 CSR 簽章。
```=
openssl x509 -req -in site.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial -out site.crt
```
![image](https://hackmd.io/_uploads/BysHxOJmR.png)

<div style="page-break-after:always;"></div>

使用 openssl x509 -in [certificate.crt] -text -noout 指令輸出你的 root CA 及 server 的 crt 檔並截圖。

![image](https://hackmd.io/_uploads/Hy5yZuyQR.png)

<div style="page-break-after:always;"></div>

以下步驟也可以達到類似效果但是能一行指令完成生成 site.pem 與 site.key，並簽證

```=
openssl req -x509 -newkey \
rsa:4096 -sha256 -nodes \
-keyout site.key \
-out site.pem \
-days 3650
```


![image](https://hackmd.io/_uploads/S1d8y81mC.png)

<div style="page-break-after:always;"></div>

修改 conf

```
sudo vim /etc/nginx/sites-available/default
```
註解掉 listen 80 的兩行並加入
```=
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
        
ssl_certificate      /home/h41173058h/ssl/site.crt;
ssl_certificate_key  /home/h41173058h/ssl/site.key;
ssl_session_timeout  5m;
ssl_protocols        TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers          ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
```

並加入一個 Server Block 重新導向到 https 的 port

```=
server {
    server_name _;
    listen 80;
    listen [::]:80;

    return 301    https://ws3.csie.ntu.edu.tw:36443/$request_uri;
}
```
![image](https://hackmd.io/_uploads/SJfekI1QA.png)
![image](https://hackmd.io/_uploads/HyT1mIkXC.png)


[REF](https://www.youtube.com/watch?v=sCJcusORiE8&t=1148s&ab_channel=GeekHour)

<div style="page-break-after:always;"></div>

## Reverse Proxy (20%)
### 13. 請使用上一個大題的 VM 完成以下問題，並將你使用的指令及完成的設定檔紀錄在 report 中。

• 請在你的 VM 的 port 8888 開啟一個 http server，並顯示 Hi! This is host A. 的字樣。此為 Host A 伺服器。
• 請在 port 9999 開啟另一個 http server，並顯示 Hi! This is host B. 的字樣。此為 Host B伺服器。
• Host A 伺服器和 Host B 伺服器可以使用任意工具架設，不一定要使用 nginx。
• 假設 public IP 為 {your_public_ip}，試著完成一份 Reverse Proxy config，能讓一個內網中的不同服務可以對外共用同一個 public IP。也就是 access http://{your_public_ip}/hostA 時，能夠 access 到 Host A 伺服器，而透過http://{your_public_ip}/hostB 能夠access 到 Host B 伺服器。

<div style="page-break-after:always;"></div>

利用GO語言建立兩個service 

```=
package main

import (
	"fmt"
	"net/http"
)

func main() {
	// 設定路由和處理器函式
	http.HandleFunc("/", handler)

	// 指定要監聽的端口
	port := "8888"

	fmt.Printf("Server is listening on port %s...\n", port)

	// 開始監聽並提供服務
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		fmt.Printf("Server failed to start: %v\n", err)
	}
}

// 處理器函式，回應網頁請求
func handler(w http.ResponseWriter, r *http.Request) {
	// 回應一個簡單的訊息
	fmt.Fprintf(w, "<h1>Hi! This is host A.</h1>")
}

```

<div style="page-break-after:always;"></div>

```=
package main

import (
	"fmt"
	"net/http"
)

func main() {
	// 設定路由和處理器函式
	http.HandleFunc("/", handler)

	// 指定要監聽的端口
	port := "9999"

	fmt.Printf("Server is listening on port %s...\n", port)

	// 開始監聽並提供服務
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		fmt.Printf("Server failed to start: %v\n", err)
	}
}

// 處理器函式，回應網頁請求
func handler(w http.ResponseWriter, r *http.Request) {
	// 回應一個簡單的訊息
	fmt.Fprintf(w, "<h1>Hi! This is host B.</h1>")
}

```

在server中加入以下區塊，並reload

```=
        location /hostA/ {
                proxy_pass http://127.0.0.1:8888/;
        }

        location /hostB/ {
                proxy_pass http://127.0.0.1:9999/;
        }
```
```
sudo systemctl reload nginx
```

成果如下
![image](https://hackmd.io/_uploads/rkplUwJXR.png)


<div style="page-break-after:always;"></div>


整份`/etc/nginx/sites-available/default`文件如下

```=
server {                             
                             
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;                                                                            
                                                           
        ssl_certificate         /home/h41173058/ssl/site.crt;
        ssl_certificate_key     /home/h41173058/ssl/site.key;
        ssl_session_timeout     5m;
        ssl_protocols           TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ciphers             ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;

        root /var/www/html;                                
                                              
        server_name _;
                                                           
       location /~h41173058/ {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                alias /home/h41173058/htdocs/;
                index index.html;
                try_files $uri $uri/ =404;
        }

        location /secret.html {
                allow 192.168.28.0/24
                deny all;
        }
        location /hostA/ {
                proxy_pass http://127.0.0.1:8888/;
        }
        location /hostB/ {
                proxy_pass http://127.0.0.1:9999/;
        }
}

    server {
            server_name _;
            listen 80;
            listen [::]:80;
            
            return 301 https://ws3.csie.ntu.edu.tw:20066/$request_uri;
    }

```