Bài này tổng hợp những gì mình tìm hiểu được trong quá trình config và cài đặt một số thứ. Mục đích để tìm hiểu và học là chính nên có gì mọi ng đọc cho vui thui nhé.
[TOC]
## Một số thuật ngữ
Ôn lại môn Nhập môn mạng máy tính cho ai đã mất gốc (bao gồm mình)
### NAT
NAT hay viết tắt của Network Address Translation là một kĩ thuật chuyển đổi đặc biệt. Kĩ thuật này giúp chuyển đổi IP nội miền sang IP ngoại miền. Quá tình chuyển đổi này tương tự như việc hỗ trợ mạng cục bộ Private dễ dàng truy cập vào mạng internet công cộng.

NAT được những Router sử dụng để chia sẻ một địa chỉ IP cho nhiều thiết bị. Router sẽ tạo một mạng LAN và gán những địa chỉ IP cục bộ tới những thiết bị truy cập vào nó. Router lúc này sẽ có nhiệm vụ như là một gateway để những thiết bị của ta ra ngoài mạng LAN thông qua một địa chỉ IP duy nhất là địa chỉ IP của router.

Thiết lập này còn có một ý nghĩa bảo mật đó là giúp che dấu hệ thống mạng nội bộ cũng như dải IP của nó. Địa chỉ IP mà thế giới bên ngoài thấy sẽ là một public ip được cấp cho router bởi ISP.
### ISP
ISP là viết tắt của Internet Service Provider. ISP là nhà cung cấp dịch vụ internet. ISP là nhà mạng giúp ta kết nối vào internet, chẳng hạn như ở VN thì FPT, Viettel là các ISPs.

### LAN
LAN là viết tắt của Local Area Network hay còn gọi là mạng cục bộ.
Mạng cục bộ là mạng máy tính kết nối các máy tính trong một khu vực giới hạn như nhà, trường học, v.v...

### WAN
WAN – Wide Area Network là mạng diện rộng
Mạng diện rộng (WAN) là mạng bao phủ một khu vực rộng (tức là, bất kỳ mạng viễn thông nào liên kết qua các ranh giới đô thị, khu vực, quốc gia hoặc quốc tế) bằng cách sử dụng các đường viễn thông cho thuê. Các thực thể kinh doanh và chính phủ sử dụng WAN để chuyển tiếp dữ liệu giữa các nhân viên, khách hàng, người mua và nhà cung cấp từ các vị trí địa lý khác nhau.

### Network Interface và switch layer
Đầu tiên là về Network interface, đây là điểm giao tiếp chính giữa máy tính và mạng. Và được định danh bởi địa chỉ MAC.
MAC là một địa chỉ vật lí hoặc địa chỉ phần cứng được gán cho mỗi thiết bị mạng. Đây là định danh duy nhất được nhúng vào card mạng của mỗi thiết bị giúp ta quản lý thiết bị trên một mạng cục bộ.

## VPN
Đầu tiên ta cần hiểu VPN là gì.
VPN là viết tắt của Virtual Private Network hay còn gọi là mạng riêng ảo.
VPN hoạt động bằng cách thiết lập một tunnel được mã hóa giữa thiết bị người dùng và máy chủ VPN. Thay vì kết nối trực tiếp ra Internet thông qua ISP, toàn bộ lưu lượng mạng sẽ được chuyển tiếp qua máy chủ VPN.
VPN sẽ đóng vai trò như một người trung gian, giúp ẩn đi địa chỉ IP thật của user khi truy cập internet và bảo vệ dữ liệu khỏi bị nghe lén.

Đường đi sẽ là từ máy của user -> ISP -> VPN Server và cuối cùng là đến Web Server. Như vậy thì thằng ISP chỉ thấy được đường kết nối của ta tới VPN Server chứ không thấy được cụ thể website mà ta truy cập tới.
Bằng cách này thì ta có thể truy cập được vào các trang web bị chặn ở nước ngoài.
Câu hỏi tiếp theo là setup như thế nào?
```
[User]
|
| (SoftEther VPN Client)
|======== ENCRYPTED TUNNEL ========|
| |
[ISP] --------------------------> [SoftEther VPN Server]
|
|
Internet / LAN
```
Ở đây mình sẽ xài Softether VPN. Tải và xem tại đây: https://www.softether.org/5-download
Tải Softether client về máy:

Xong xuôi thì một cửa sổ như thế này sẽ hiện lên:

Click tạo một Virtual Network Adapter

SoftEther VPN Client tạo một card mạng ảo trên máy host, mọi traffic đi vào card này được đóng gói, gửi qua VPN, và được Virtual Hub ở server xử lý. Document của Softether cũng có nói rõ đến cái này: [Doc](https://www.softether.org/4-docs/1-manual/4._softether_vpn_client_manual/4.3_virtual_network_adapter)
```
[Ứng dụng]
↓
[Virtual Network Adapter] ← SoftEther Client tạo
↓
[SoftEther VPN Engine]
↓
[Internet]
↓
[VPS - SoftEther VPN Server]
```
Mở CMD lên check ipconfig thì thấy có một địa chỉ IP mới xuất hiện:
```
Unknown adapter VPN - VPN Client:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
```
Bài toán tiếp theo là thiết lập VPN Server.
Vào thời điểm mình viết bài này thì github student developer pack của mình vẫn chưa được duyệt nên mình chưa test được cái vps của digital ocean thành ra phải xài free ở đây: [Link](https://www.vpngate.net/en/)
Thiết lập thành công thì nó sẽ hiện ra như này

Nhưng vẫn còn khá nhiều thứ cần tìm hiểu kĩ trong phần settings của nó:

Đầu tiên là phần Destination VPN Server.
Ở mục hostname ta sẽ điền địa chỉ IP hoặc domain của server.
Port ta sẽ điền 443 và Virtual Hub Name là VPNGATE. Lý do tại sao lại điền cổng 443? Cổng 443 là cổng mặc định cho giao thức HTTPs
Khi ta truy cập bất kỳ trang web nào sử dụng giao thức HTTPS , trình duyệt sẽ tự động khởi tạo một kết nối bảo mật thông qua cổng 443. Khi ta đặt cổng 443 như vậy th
Việc settings port 443 như vậy giúp ta vượt qua tường lửa bằng cách che giấu luồng dữ liệu VPN giống như lưu lượng HTTPS tiêu chuẩn.
Tiếp theo đến Proxy Server: Ta sẽ chọn Direct TCP/IP Connection tức là kết nối trực tiếp từ VPN Client tới VPN Server mà không thông qua proxy.
Phần server certificate tạm thời mình chưa tìm hiểu rõ vì chưa thử thiết lập trên VPS riêng.
### Tunneling
https://www.cloudflare.com/learning/network-layer/what-is-tunneling/
Tunneling là một kĩ thuật truyền tin qua mạng bằng cách đóng gói các gói tin ( tức là ta có một gói tin lớn, đóng gói gói tin nhỏ hơn rồi chuyển đi) và ở đích đến thì người nhận có thể mở ra và xem (encap và decap).
Mục đích của việc đóng gói như vậy là để đi qua một mạng trung gian mà bình thường gói tin. không đi được.
Một ví dụ dễ hiểu là việc ta gửi thư thông qua bưu điện, thay vì gửi trực tiếp lá thư đó thì ta sẽ bỏ vào phong bì, ở trên phong bì này sẽ chứa thông tin về người nhận, địa chỉ của bức thư.
Một gói tin đi qua tunnel cũng tương tự như vậy, bao gồm 2 phần chính: phần đầu tiên nó sẽ chứa thông tin về kiểu protocol và đích đến của gói tin gốc còn phần payload của nó cũng chính là payload của gói tin gốc.
Một lợi ích khác của việc đóng gói gói tin có thể kể đến như sau: Giả sử ta muốn thiết lập kết nối WAN giữa 2 cụm mạng A và B. Giao thức mà ta muốn triển khai là IPv6, tuy nhiên có một số network giữa 2 cụm A và B chỉ hỗ trợ IPv4. Lúc này ta sẽ đóng gói gói tin IPv6 vào trong gói tin IPv4 để có thể tiếp tục kết nối
https://viblo.asia/p/ky-thuat-chuyen-doi-ipv4-sang-ipv6-su-dung-cong-nghe-duong-ham-tunnel-m68Z08XXZkG
Ngoài ra tunnel cũng có hỗ trợ mã hóa để thiết lập kênh truyền tin an toàn.
Nổi bật nhất như ta đã biết đó là VPN Tunnel
Đa số VPNs sử dụng IPsec protocol. IPsec là một nhóm các protocols chạy trực tiếp trên IP của tầng mạng (network layer)
https://viblo.asia/p/giao-thuc-ipsec-trong-linh-vuc-an-toan-thong-tin-oOVlYdPQZ8W
Khi một user kết nối thiết bị tới VPN, mặc định toàn bộ lưu lượng mạng của máy sẽ đi qua VPN Tunnel. Tuy nhiên việc kết nối thông qua VPN Tunnel sẽ khiến tốc độ mạng trở nên chậm đi và không phải kết nối nào cũng cần tới VPN. Vì vậy ta mới cần đến một cơ chế gọi là split tunneling
Split tunneling cho phép một số mạng/đích cần thiết đi qua VPN còn phần còn lại thì không
Tiếp theo ta có khái niệm về GRE Tunneling
GRE là Generic Routing Encapsulation, đây là một giao thức được phát triển bởi Cisco, cho phép đóng gói nhiều loại giao thức lớp Network trong các liên kết Point-to-Point
Một GRE Tunnel được sử dụng khi các gói dữ liệu cần được gửi giữa các mạng khác nhau thông qua internet. Với GRE được cấu hình, 1 đường hầm ảo được tạo giữa 2 Router và các gói tin gửi giữa 2 mạng nội bộ sẽ được truyền qua GRE Tunnel.
Tuy nhiên GRE Tunnel không được mã hóa, để bảo vệ dữ liệu ta cần sử dụng IPsec kết hợp kèm với GRE.
IPsec GRE Tunnel về cơ bản giống với IPsec VPN site to site khi cả hai giao thức đều tạo 1 tunnel để kết nối giữa 2 site cho phép truyền dữ liệu qua chúng.
Một khái niệm đơn giản gần gũi hơn đó là IP-in-IP. IP-in-IP là một giao thức tunneling có vai trò đóng gói các gói tin IP vào bên trong các gói tin IP khác rồi gửi chúng đi —> việc gửi đi không hề được thiết lập thêm các thuật toán mã hóa cho nên sẽ không an toàn và mục đích chính của việc sử dụng giao thức này là để phục vụ định tuyến/kết nối giữa các mạng khi mạng trung gian không hỗ trợ trực tiếp
## DHCP/DNS
### DHCP Server
Đầu tiên là khái niệm về giao thức DHCP.
DHCP là một giao thức hoạt động ở lớp Application.
DHCP là viết tắt của Dynamic host configuration protocol. Vậy thì giao thức này nó làm gì?
Đầu tiên, giao thức này là một giao thức mạng tự động cấp phát IP và các thông tin cấu hình mạng khác cho các thiết bị trong mạng.
Hiểu một cách đơn giản, đây là một giao thức mạng cho phép một máy chủ (DHCP Server) tự động cấp phát địa chỉ IP và các thông tin cấu hình mạng khác cho các thiết bị (Client) trong hệ thống.
DHCP Server (Dynamic Host Configuration Protocol Server) là một máy chủ hoặc thiết bị mạng, như router hoặc switch, có chức năng tự động gán địa chỉ IP và các thông tin cấu hình mạng khác cho các thiết bị (máy khách DHCP) khi chúng kết nối vào mạng.
Quy trình cấp phát địa chỉ IP của DHCP bao gồm bốn giai đoạn: Discover, Offer, Request, và Acknowledge

Sơ đồ chi tiết 4 bước:

### DNS
DNS là viết tắt của domain name system. Hiểu đơn giản thì DNS hoạt động như một danh bạ điện thoại. Chẳng hạn ta muốn tìm kiếm thông tin trên internet, việc đầu tiên ta làm là nhập url google.com vào web browsers. Nhưng các web browsers tương tác thông qua Internet Protocol hay còn gọi là IP addresses nên nó không thể hiểu google.com rốt cuộc là gì. Lúc này DNS sẽ vào việc, nó sẽ chuyển đổi google.com thành một địa chỉ IP để Web browsers có thể hiểu và giúp ta truy cập vào website.
## Nginx
Nhân tiện phần này mình sẽ note luôn về nhóm lệnh systemctl, một nhóm lệnh phục vụ cho việc quản lí dịch vụ trên Linux.
### Systemctl
Lệnh systemctl cho phép ta tương tác với systemd. Systemd quản lí các unit. Có tổng cộng 12 loại unit khác nhau và loại phổ biến nhất là service.
**Start service**
```
sudo systemctl start nginx.service
```
**Stop service**
```
sudo systemctl stop nginx.service
```
**Restart service**
```
sudo systemctl restart nginx.service
```
Mặc định thì các service trong linux không được tự động bật khi start hệ điều hành. Để làm điều đó thì cần phải enable service
```
sudo systemctl enable nginx.service
```
Disable thì cũng tương tự:
```
sudo systemctl disable nginx.service
```
Để xem thông tin của các unit được hệ thống load vào bộ nhớ ta sử dụng lệnh `systemctl list-units`. Muốn list luôn cả các unit files được load vào memory nhưng chưa active thì sử dụng `systemctl list-units --all`
List các unit files chưa load vào memory thì dùng
```
systemctl list-unit-files
```

Còn để xem trạng thái cái service unit thì có thể sử dụng lệnh `status option` của systemctl.
```
systemctl status nginx.service
```
Và quan trọng nhất, để enable systemd thì ta cần thêm dòng này vào trong file `/etc/wsl.conf`
```
[boot]
systemd=true
```
Xem thêm tại doc của Microsoft: https://learn.microsoft.com/en-us/windows/wsl/systemd
### Về nginx
## mTLS - Mutual TLS
mTLS là viết tắt của Mutual Transport Layer Security, phát triển từ TLS.
Trước tiên ta nhắc lại cách mà TLS hoạt động:

1. 'Client hello' message: Client bắt đầu quy trình bắt tay bằng cách gửi một gói tin hello tới server. Trong message cũng đính kèm thêm thông tin về phiên bản TLS mà client hỗ trợ, các thuật toán mã hóa cùng một số thông tin khác
2. 'Server hello' message: Server đáp lại gói tin hello của client bằng việc gửi lại một gói tin hello khác. Gói tin này cũng bao gồm chứng chỉ SSL của server, và một số thông tin khác.
3. Authentication: Client sẽ kiểm tra chứng chỉ của server và kiểm tra thêm rằng liệu chứng chỉ này có được một CA tin cậy kí hay không. Ngoài ra nó cũng sẽ kiểm tra thêm các thông tin khác để đảm bảo rằng mình đang giao tiếp với server thực sự.
4. Premaster key: Client sinh một khóa ngẫu nhiên gọi là premaster-key rồi gửi cho Server key đã mã hóa bằng public key của server. Sau đó server sẽ giải mã và lấy lại key này bằng khóa riêng của mình.
5. Như vậy cả hai đều đạt được một khóa chung và sẽ dùng khóa này để mã hóa các đoạn tin nhắn về sau.
-> Vai trò của TLS là giúp đảm bảo 3 yếu tố CIA khi giao tiếp qua mạng.
mTLS sẽ mở rộng quy trình xác thực của TLS ra, thay vì chỉ mỗi client xác minh server thì giờ đây server cũng sẽ xác minh client bằng cert bên phía client.
Demo: Bây giờ ta sẽ đóng vai trò là CA root để xác minh cho cert từ phía server và client. Server và Client sẽ cung cấp các file, server.crt cũng như là client.crt cho bên CA để cung cấp cert. Hai file server.key và client.key là các khóa bí mật sẽ được mỗi bên tự quản lí.
File ca.conf để tạo ca.crt trông như sau:
```
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = localhost
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
```

Cấu trúc cây thư mục:
```
.
├── certs
│ ├── ca.conf
│ ├── ca.crt
│ ├── ca.key
│ ├── ca.srl
│ ├── client.crt
│ ├── client.csr
│ ├── client.key
│ ├── server.crt
│ ├── server.csr
│ └── server.key
├── client
│ └── main.go
└── server
└── main.go
```
Quy trình thực hiện như sau:
Tạo cert cho client và server:
```
openssl req -newkey rsa:2048 -nodes -keyout ca.key -x509 -days 365 -out ca.crt -subj "/CN=MyCA"
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile ca.conf -extensions v3_req
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=MyClientUser"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
```
Bên phía client:
```go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
caCert, err := os.ReadFile("../certs/ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
cert, err := tls.LoadX509KeyPair("../certs/client.crt", "../certs/client.key")
if err != nil {
log.Fatal(err)
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
},
},
}
resp, err := client.Get("https://localhost:8443")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %s\nBody: %s\n", resp.Status, body)
}
```
Bên phía server:
```go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"net/http"
"os"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello %s, mTLS handshake success!", r.TLS.PeerCertificates[0].Subject.CommonName)
}
func main() {
caCert, err := os.ReadFile("../certs/ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
ClientCAs: caCertPool,
ClientAuth: tls.RequireAndVerifyClientCert,
MinVersion: tls.VersionTLS13,
}
server := &http.Server{
Addr: ":8443",
TLSConfig: tlsConfig,
Handler: http.HandlerFunc(handler),
}
err = server.ListenAndServeTLS("../certs/server.crt", "../certs/server.key")
if err != nil {
log.Fatal(err)
}
}
```
Chạy hai file `main.go` trong từng thư mục và quan sát kết quả:
```
go run main.go
```

## HTTP/HTTPS với Python
https://www.digitalocean.com/community/tutorials/python-simplehttpserver-http-server
## Certificate - SSL/TLS
Ở phần này ta sẽ nói về thư viện OpenSSL và cách tạo certificate cho web server HTTP.
### PKI và cách triển khai
PKI cung cấp nền tảng bảo mật bằng cách sử dụng các cặp khóa bất đối xứng và chứng chỉ số. Trong trường hợp của ta thì thuật toán mã hóa bất đối xứng sẽ là ECC. Các quá trình tạo khóa, đăng ký và phát hành chứng chỉ, phân phối và lưu trữ chứng chỉ, xác thực danh tính, mã hóa và giải mã dữ liệu, chữ ký số và quản lý vòng đời chứng chỉ hoạt động đồng bộ để đảm bảo an ninh, tính toàn vẹn và xác thực trong các giao dịch và trao đổi thông tin trực tuyến.
Quy trình hoạt động của PKI như sau:
- Người dùng:
- Tạo một cặp khóa gồm public key và private key
- Public key được chia sẻ rộng rãi trong khi private key phải được giữ an toàn và bí mật
- Yêu cầu cấp chứng chỉ
- Người dùng hoặc thiết bị gửi một yêu cầu chứng chỉ (Certificate Signing Request – CSR) đến một cơ quan chứng thực (Certificate Authority – CA).
- Yêu cầu này bao gồm khóa công khai và thông tin nhận dạng của người dùng hoặc thiết bị.
CA sau đó sẽ xác minh danh tính của người dùng để đảm bảo rằng họ là người sử hữu hợp pháp của khóa công khai. CA sau đó sẽ cấp chứng chỉ cho người dùng. Nếu CA xác minh thành công danh tính của người dùng, họ sẽ cấp cho người dùng một chứng chỉ kĩ thuật số. Chứng chỉ này chứa thông tin về danh tính của người dùng và khóa công khai của họ và được kí bởi private key của CA.
Chứng chỉ số này sau đó sẽ được gửi lại cho người dùng hoặc thiết bị, và có thể được phân phối cho bất kì ai cần xác thực danh tính của người dùng hoặc thiết bị đó. Khóa bí mật cần được giữ kín bởi người dùng hoặc thiết bị và không được chia sẻ với bất kì ai khác.
Khi cần xác thực danh tính, người dùng hoặc thiết bị sẽ cung cấp chứng chỉ số của mình. Bên nhận sẽ kiểm tra chữ ký số trên chứng chỉ để xác nhận nó được phát hành bởi một CA đáng tin cậy.
Bên nhận cũng cần xác minh khóa công khai trong chứng chỉ thuộc về người dùng hoặc thiết bị được nhận.
Người dùng sử dụng khóa công khai để mã hóa thông tin: Khi cần gửi dữ liệu an toàn, bên gửi sử dụng khóa công khai của bên nhận (từ chứng chỉ số của bên nhận) để mã hóa dữ liệu. Chỉ bên nhận mới có thể giải mã dữ liệu này bằng khóa bí mật tương ứng.
### Triển khai các thuật toán chữ kí số bằng OpenSSL
Tham khảo tại: https://docs.openssl.org/3.1/man1/openssl-ec/#synopsis
Kiểm tra phiên bản OpenSSL hiện tại và xem các curve được hỗ trợ:
```bash
openssl version
openssl ecparam -list_curves
```
<img alt="image" src="https://github.com/user-attachments/assets/4f9b49c9-53e1-4abb-b764-9f39e022a8c5" />
Tạo private key và public key dùng cho việc kí tin nhắn
```bash
openssl ecparam -name secp384r1 -genkey -noout -out private.key
openssl ec -in private.key -pubout -out public.pem
```
<img width="335" height="70" alt="image" src="https://github.com/user-attachments/assets/3f6d3498-53cb-4572-9f3d-45953f376869" />
Để kí một message bất kì, đầu tiên chuyển message đó vào file cần lưu:
```bash
echo "53edc760b7a66e1f4d8b0c5715725ee447b79c0" > hash.hexxxd -r -p hash.hex > hash.bin
```
Kí bằng private key:
```bash
openssl pkeyutl -sign -inkey private.key -in hash.bin -out signature.bin
```
Xem định dạng của file signature theo format ASN.1
```bash
openssl asn1parse -in signature.bin -inform der
```
<img alt="image" src="https://github.com/user-attachments/assets/33283739-11c9-4705-900c-bed10b5aa70b" />
Đối với thuật toán kí bằng ECDSA, chữ kí số sẽ được lưu dưới dạng một cặp số $(r,s)$
Xác minh chữ kí bằng public key:
```bash
openssl pkeyutl -verify -inkey public.pem -pubin -in hash.bin -sigfile signature.bin
```
Thông báo thành công:
<img alt="image" src="https://github.com/user-attachments/assets/8aafcf5e-dbd0-4aef-8aa8-025dd1921f68" />
Giả sử ta muốn kí và xác minh trực tiếp cho một file bất kì thì có thể làm như sau:
```bash
echo "private message" > data.txt
openssl dgst -sha256 -sign private.key -out signature.bin data.txt
```
Xác minh bằng:
```bash
openssl dgst -sha256 -verify public.pem -signature signature.bin data.txt
```
Kết quả:
<img alt="image" src="https://github.com/user-attachments/assets/da68355c-f8ad-4935-a62b-ca3776924920" />
Tiếp theo ta sẽ tạo chứng chỉ cho HTTP Server sử dụng thuật toán ECC. Ta sẽ sử dụng nginx cho HTTP Server.
Việc đầu tiên là tạo một private key mới cho server trong thư mục `/etc/nginx/ssl` và cấp quyền 600 cho nó:
```
cd /etc/nginx
sudo mkdir ssl
cd ssl
sudo openssl genpkey -algorithm EC \
-pkeyopt ec_paramgen_curve:secp384r1 \
-pkeyopt ec_param_enc:named_curve \
-out server-ecc.key
sudo chmod 600 server-ecc.key
```
Xuất public key để gửi xác thực:
```
sudo openssl pkey -in server-ecc.key -pubout -out server-ecc.pub.pem
```
Tạo một file cấu hình cho HTTP Server:
```
[ req ]
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = VN
ST = HCM
L = HCM
O = Demo
OU = Crypto
CN = localhost
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
```
Sau đó tạo file CSR
```
sudo openssl req -new -key server-ecc.key -out server.csr -config server.cnf
```
Ở đây ta sẽ đóng vai trò là Trusted CA để kí cho chứng chỉ của server
Tạo CA Key và CA cert:
```
sudo openssl genpkey -algorithm EC \
-pkeyopt ec_paramgen_curve:secp384r1 \
-pkeyopt ec_param_enc:named_curve \
-out ca.key
sudo openssl req -x509 -new -key ca.key -sha256 -days 3650 \
-subj "/C=VN/ST=HCM/L=HCM/O=DemoLab/OU=CA/CN=DemoLab Root CA" \
-out ca.crt
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 825 -sha256 \
-extfile server.cnf -extensions req_ext
```
Tiếp theo ta cần cấu hình cho nginx server:
File cấu hình sẽ nằm trong thư mục `sites-available`
```
sudo nano default
```
Đầu tiên là thêm mã trạng thái 301 cho HTTP để thông báo chuyển hướng vĩnh viễn URL của server này sang một địa chỉ URL mới. Ở đây ta sẽ redirect các kết nối HTTP sang HTTPS
```
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
# Add index.php to the list if you are using PHP
server_name _;
return 301 https://$host$request_uri;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}
```
Cuối cùng là cấu hình port 443 cho HTTPS:
```
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server-ecc.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
try_files $uri $uri/ =404;
}
}
```
Bước cuối cùng là import chứng chỉ CA đã được kí cho server để enable HTTPs.
<img alt="image" src="https://github.com/user-attachments/assets/5c6324ec-39ba-489d-a851-b297f767b408" />
Chọn Trusted Root Certification Authorities.
Khởi động lại nginx:
```
sudo systemctl restart nginx
```
Kiểm tra chứng chỉ:
<img width="398" height="300" alt="image" src="https://github.com/user-attachments/assets/0ea585a6-3081-4049-b4f0-6cfabee4078a" />
<img width="697" height="841" alt="image" src="https://github.com/user-attachments/assets/42d1db7d-16f7-4263-a91b-c7201a37356b" />
Hoặc cũng có thể check bằng `curl`:
```
curl --cacert /etc/nginx/ssl/ca.crt -vk https://localhost
```
Nếu triển khai trên VPS thì cũng làm tương tự các bước như trên, chỉ khác là thay CN bằng Public IP của VPS là được.
## SSH - Secure Shell
## ECH - Encrypted Client Hello
## WSL - Virtual Switch
Hôm bữa mình tìm được cái repo này.
https://github.com/dantmnf/WSLAttachSwitch
Ý nghĩa của nó?
Trước tiên mình cần phải hiểu sơ qua về Hyper-V Networking.
Xem cách tải Hyper-V Manager tại đây nếu như máy mọi người không có: [Forum](https://learn.microsoft.com/en-us/answers/questions/2194529/enabling-hyper-v-on-windows-10-home?page=2)
Tải bằng lệnh sau:
```cmd
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V -All /LimitAccess /ALL
pause
```
Lưu đống lệnh trên vào một file có định dạng là `.bat` rồi chạy dưới quyền Admin

Sau khi chạy xong thì mọi người vào kiểm tra lại

Về tài liệu thì mình đọc Doc của Microsoft(tiện vl) [Hyper-V](https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/)