Chắc hẳn bạn đã từng trải qua tình huống này: Đẩy code lên nhánh main vào lúc nửa đêm, đinh ninh rằng hệ thống sẽ tự động hoàn tất quá trình build và deploy. Nhưng chỉ vài phút sau, pipeline báo đỏ rực. Khi mở log kiểm tra, nguyên nhân không xuất phát từ lỗi biên dịch (compilation error), mà là do GitHub trả về thông báo Rate limit exceeded, hoặc IP Datacenter của máy chủ runner đã bị Apple’s Swift Package Registry chặn do phát sinh lưu lượng quá dồn dập.
Khi các máy chủ build CI/CD (như GitHub Actions Runner, GitLab CI Runner) kết nối trực tiếp ra mạng công cộng, chúng bộc lộ rõ địa chỉ IP thực cùng siêu dữ liệu (metadata) của hệ thống nội bộ. Các dịch vụ bên ngoài có thể hạn chế truy cập, thậm chí chặn kết nối nếu phát hiện lưu lượng bất thường.
Một giải pháp mang lại hiệu quả cao cho bài toán này là triển khai Proxy SOCKS5 cho CI/CD Pipeline. Việc chuyển hướng lưu lượng ra ngoài (outbound traffic) qua một cổng kiểm soát tập trung (Egress Gateway) giúp bảo vệ hạ tầng gốc và giữ cho luồng build duy trì trạng thái ổn định. Vậy làm thế nào để xây dựng một đường hầm mạng an toàn, tuân thủ mô hình Zero Trust mà vẫn duy trì tốc độ xử lý nhanh chóng cho dự án Swift?

Mô hình Egress Proxy giúp cô lập máy chủ CI/CD Runner, định tuyến luồng traffic qua điểm kiểm soát tập trung SOCKS5.
Bản chất của Proxy SOCKS5 trong luồng CI/CD (góc nhìn DevOps)
Nhiều kỹ sư hệ thống thường có thói quen sử dụng lại HTTP Proxy cho mọi tác vụ kết nối mạng. Tuy nhiên, luồng làm việc tự động trong CI/CD đòi hỏi khả năng xử lý linh hoạt hơn rất nhiều.
Egress Proxy: Kiểm soát điểm ra tập trung theo mô hình Zero Trust
Thay vì cấp quyền truy cập Internet trực tiếp cho máy chủ build, chúng ta áp dụng mô hình Egress Proxy nhằm xây dựng giải pháp Proxy cho doanh nghiệp trong mô hình Zero Trust, giúp tối ưu hóa hệ thống mạng. Máy chủ CI/CD Runner sẽ được đặt trong một mạng cô lập. Toàn bộ thao tác kéo thư viện, tải Docker Image hay kết nối đến API nội bộ đều đi qua một cổng kiểm soát tập trung chạy giao thức SOCKS5.
Cách làm này mang lại giá trị thực tiễn trong công tác kiểm toán (audit). Đội ngũ quản trị chỉ cần theo dõi tập tin nhật ký (log) tại máy chủ Proxy để nắm bắt chính xác pipeline đang gửi dữ liệu đến đâu. Nếu một thư viện bên thứ ba chứa mã độc tìm cách đánh cắp biến môi trường và gửi ra địa chỉ lạ, trạm kiểm soát Egress Proxy sẽ ghi lại dấu vết để kỹ sư kịp thời ngăn chặn.
Khác biệt cốt lõi giữa SOCKS5 và HTTP Proxy: Tầng phiên và hỗ trợ UDP
HTTP Proxy hoạt động ở Tầng 7 (Application Layer) trong mô hình OSI, đồng nghĩa với việc nó tiếp nhận và phân tích các yêu cầu theo cấu trúc HTTP/HTTPS. Nếu quy trình CI/CD sử dụng lệnh git clone [email protected]:... (chạy qua OpenSSH trên cổng 22), hoặc kết nối trực tiếp đến cơ sở dữ liệu qua TCP thô, HTTP Proxy sẽ từ chối hoặc làm gián đoạn gói tin do thiếu HTTP Header. Thêm vào đó, HTTP Proxy không hỗ trợ giao thức UDP.
Trái lại, SOCKS5 hoạt động ở Tầng 5 (Session Layer). Giao thức này đóng vai trò như một ống dẫn trong suốt, chuyển tiếp nguyên bản chuỗi byte nhị phân thô (raw bytes). SOCKS5 hỗ trợ đầy đủ cả TCP và UDP (thông qua lệnh udpassociate). Nhờ khả năng xử lý UDP, SOCKS5 đáp ứng tốt các tác vụ phân giải tên miền từ xa, kết nối mạng riêng ảo hoặc các dịch vụ truyền phát dữ liệu thời gian thực mà HTTP Proxy không thể đảm đương.
Để hiểu rõ hơn về các chuẩn giao thức ở tầng phiên này, bạn có thể tham khảo thêm bài phân tích so sánh những điểm khác biệt giữa SOCKS4 và SOCKS5.
Ngăn chặn rò rỉ DNS (DNS Leaks) với tiền tố socks5h://
Một thiếu sót phổ biến khi thiết lập mạng là hiện tượng rò rỉ DNS (DNS Leaks). Kể cả khi tiến trình tải code đã trỏ về proxy, nếu máy chủ Runner vẫn tự phân giải tên miền cục bộ, các truy vấn DNS (chứa domain nội bộ hoặc registry riêng) vẫn bị gửi ra ngoài dưới dạng văn bản rõ (clear-text) qua cổng UDP 53. Hơn nữa, nếu Runner nằm trong mạng cô lập không có DNS ngoài, lệnh build sẽ báo lỗi Could not resolve host.
Bằng cách sử dụng định dạng socks5h:// (ký tự h đại diện cho hostname), client sẽ chuyển tiếp nguyên vẹn chuỗi tên miền đến máy chủ SOCKS5. Việc tra cứu DNS sẽ do máy chủ Proxy thực hiện từ xa (Remote DNS Resolution). Kỹ thuật này triệt tiêu rủi ro rò rỉ DNS và khắc phục tình trạng bị chặn IP do phân giải sai địa chỉ từ mạng nội bộ.

Cơ chế phân giải tên miền từ xa (Remote DNS Resolution) bằng tiền tố socks5h:// giúp triệt tiêu nguy cơ rò rỉ DNS ra mạng bên ngoài.
Chuẩn bị kiến trúc và môi trường Ubuntu VPS
Chúng ta sẽ thiết lập mô hình gồm hai máy chủ độc lập trên hệ điều hành Ubuntu 26.04 LTS (Resolute Raccoon) hoặc Ubuntu 24.04 LTS. Việc sử dụng các phiên bản hỗ trợ dài hạn giúp hạ tầng CI/CD vận hành bền bỉ qua nhiều năm.
Phân tách vai trò: Bastion Host và CI Runner
- Bastion Host (máy chủ Proxy): Một VPS sở hữu IP tĩnh ổn định, đóng vai trò làm điểm trung chuyển dữ liệu ra ngoài Internet.
- CI Runner (máy chủ Build): VPS chịu trách nhiệm biên dịch mã nguồn. Máy chủ này bị đóng các cổng ra ngoài trực tiếp và chỉ giao tiếp với cổng dịch vụ của Bastion Host.
Khởi tạo môi trường Swift 6.4 chuẩn CI với swiftly
Phiên bản Swift 6.4 mang đến nhiều tối ưu cho công cụ Swift Build trên nền tảng Linux. Để thiết lập môi trường gọn gàng và dễ tự động hóa, chúng ta sử dụng công cụ quản lý phiên bản chính thức swiftly.
Tải và cài đặt công cụ swiftly trên máy CI Runner:
curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz
tar zxf swiftly-$(uname -m).tar.gz
./swiftly init --assume-yes --skip-install
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh"
Cài đặt và kích hoạt Swift 6.4:
swiftly install 6.4.0
swiftly use 6.4.0
swift --version
Khi môi trường biên dịch đã sẵn sàng, chúng ta bước vào khâu triển khai đường hầm mạng.
2 phương án thiết lập Proxy SOCKS5 cho CI/CD Pipeline
Tùy vào quy mô hạ tầng và số lượng worker, bạn có thể tham khảo một trong hai phương án định tuyến dưới đây.
Phương án 1: SSH Dynamic Port Forwarding và autossh (gọn nhẹ)
Khi cần một đường hầm mã hóa nhanh chóng mà không muốn cài thêm phần mềm trung gian, cơ chế Dynamic Port Forwarding (ssh -D) tích hợp sẵn trong OpenSSH là một lựa chọn tiện lợi. Để ngăn ngừa sự cố đứt kết nối ngầm khi đường truyền tạm thời gián đoạn, chúng ta kết hợp lệnh này với autossh và đưa vào quản lý bởi systemd.
Bước 1: Cài đặt và tạo SSH Key
Trên máy CI Runner, cài đặt các công cụ cần thiết và tạo cặp khóa xác thực tự động (không dùng mật khẩu):
sudo apt update && sudo apt install -y autossh openssh-client
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_proxy -N ""
ssh-copy-id -i ~/.ssh/id_ed25519_proxy.pub proxy_user@IP_Bastion_Host
Bước 2: Khởi tạo Systemd Service
Tạo tập tin cấu hình /etc/systemd/system/autossh-socks5.service:
[Unit]
Description=AutoSSH SOCKS5 Dynamic Tunnel
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=ubuntu
ExecStart=/usr/bin/autossh -M 0 -N -D 127.0.0.1:1080 \
-i /home/ubuntu/.ssh/id_ed25519_proxy \
-o "ServerAliveInterval 60" \
-o "ServerAliveCountMax 3" \
-o "ExitOnForwardFailure yes" \
-o "StrictHostKeyChecking=accept-new" \
proxy_user@IP_Bastion_Host
Restart=always
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
Kích hoạt dịch vụ bằng lệnh sudo systemctl enable --now autossh-socks5. Một cổng SOCKS5 cục bộ sẽ mở tại địa chỉ 127.0.0.1:1080. Dữ liệu gửi vào cổng này được mã hóa theo giao thức SSH và truyền tới Bastion Host trước khi đi tiếp.

Tiến trình AutoSSH liên tục gửi các tín hiệu giữ nhịp (keep-alive) để đảm bảo đường hầm định tuyến luôn trong trạng thái kết nối.
Phương án 2: Dedicated Proxy với Dante-server (quy mô doanh nghiệp)
Nếu bạn vận hành một cụm nhiều máy chủ Runner cùng chia sẻ một trạm trung chuyển, Dante-server là một giải pháp chuyên trách với khả năng phân quyền truy cập và kiểm soát người dùng chi tiết. Các lệnh cấu hình sau được thực hiện trực tiếp trên Bastion Host.
Bước 1: Cài đặt và tạo tài khoản xác thực
Tạo một tài khoản chuyên biệt không có quyền truy cập shell để bảo vệ an toàn cho hệ điều hành:
sudo apt update && sudo apt install -y dante-server
sudo useradd --system --no-create-home --shell /usr/sbin/nologin proxy_ci
sudo passwd proxy_ci
Bước 2: Thiết lập file cấu hình danted.conf
Mở file /etc/danted.conf và điền cấu hình (giả định card mạng kết nối Internet là eth0):
logoutput: syslog
internal: eth0 port = 1080
external: eth0
clientmethod: none
socksmethod: username
user.privileged: root
user.notprivileged: nobody
# Cho phép kết nối từ dải mạng nội bộ của CI Runner
client pass {
from: 10.0.0.0/24 to: 0.0.0.0/0
log: connect error
}
# Bắt buộc xác thực tài khoản với các lệnh kết nối SOCKS
socks pass {
from: 10.0.0.0/24 to: 0.0.0.0/0
command: bind connect udpassociate
log: connect error
socksmethod: username
}
Khởi động lại dịch vụ bằng lệnh sudo systemctl restart danted. Lúc này, Bastion Host đã sẵn sàng phục vụ các luồng build từ xa có yêu cầu đăng nhập.
Tích hợp đường hầm SOCKS5 vào hệ sinh thái Pipeline
Sau khi đường hầm được thiết lập, công việc tiếp theo là cấu hình để công cụ trong pipeline tiếp nhận proxy một cách đồng bộ.
Tận dụng Native Proxy của Swift 6.4 và Git CLI
Trước đây, kỹ sư thường phải dùng các phần mềm can thiệp thư viện hệ thống (như proxychains4) để ép lệnh build chạy qua proxy. Hiện nay, với đề xuất SE-0549 được áp dụng chính thức, Swift Package Manager (SPM) đã tích hợp sẵn khả năng cấu hình proxy nguyên bản cho các kết nối mạng (tải binary artifacts, registry, SDKs).
Thiết lập SOCKS5 Proxy cho Swift Package Manager trên máy Runner:
swift package config set-proxy --global --http socks5://127.0.0.1:1080 --https socks5://127.0.0.1:1080
Song song đó, vì SPM sử dụng Git để fetch mã nguồn từ các kho lưu trữ, bạn cần cấu hình Git CLI để định tuyến an toàn và chống rò rỉ DNS.
Định tuyến Git HTTPS qua SOCKS5 với chế độ phân giải DNS từ xa:
git config --global http.proxy socks5h://127.0.0.1:1080
git config --global https.proxy socks5h://127.0.0.1:1080
Đối với các kho mã nguồn nội bộ truy cập bằng khóa SSH (git@...), hãy khai báo trong file ~/.ssh/config của user chạy CI:
Host github.com
User git
ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p
Cấu hình Docker toàn diện: Phân tách Docker Daemon và Docker Client
Bước 1: Proxy cho Docker Daemon (kéo Image qua SOCKS5)
File cấu hình client không có quyền can thiệp vào lệnh docker pull. Để kéo các image như swift:6.4-ubuntu26.04 thông qua proxy, bạn khai báo trực tiếp trong /etc/docker/daemon.json với cú pháp kebab-case:
{
"proxies": {
"http-proxy": "socks5://127.0.0.1:1080",
"https-proxy": "socks5://127.0.0.1:1080",
"no-proxy": "localhost,127.0.0.1"
}
}
Sau đó nạp lại cấu hình:
sudo systemctl daemon-reload && sudo systemctl restart docker
Bước 2: Proxy cho Docker Client (dành cho tiến trình build bên trong container)
Để các biến môi trường proxy tự động bơm vào môi trường thực thi của container khi chạy docker build hoặc docker run, hãy tạo hoặc chỉnh sửa file ~/.docker/config.json của user chạy CI với cú pháp camelCase:
{
"proxies": {
"default": {
"httpProxy": "socks5://127.0.0.1:1080",
"httpsProxy": "socks5://127.0.0.1:1080",
"noProxy": "localhost,127.0.0.1"
}
}
}
Sự kết hợp này giúp quy trình từ lúc tải base image đến khi compile code bên trong container đều đi qua đường hầm an toàn mà không cần can thiệp cờ mạng phức tạp.

Việc cấu hình độc lập proxy cho Docker Daemon và môi trường bên trong container mang lại hiệu quả định tuyến toàn diện.
Quản lý thông tin xác thực an toàn qua Secret Manager
Trong quy chuẩn DevSecOps, thôngquan đăng nhập, địa chỉ IP máy chủ proxy và SSH private key không nên lưu trữ dưới dạng văn bản rõ (plaintext) trong kho mã nguồn hay Dockerfile.
Hãy tận dụng hệ thống quản lý biến bí mật của nền tảng CI/CD:
- GitHub Actions: Khai báo thông tin trong mục
Settings > Secrets and variables > Actions. Truy xuất vào tệp workflow bằng cú pháp ${{ secrets.PROXY_HOST }} và ${{ secrets.PROXY_PASS }}.
- GitLab CI: Sử dụng tính năng
CI/CD Variables, kích hoạt cờ Masked để nền tảng tự động che các giá trị nhạy cảm trên màn hình log nếu có tiến trình vô tình hiển thị chúng.
Giải pháp thay thế: Tự động hóa định tuyến toàn cục với TUN Mode
Nếu dự án của bạn là một hệ thống đa ngôn ngữ (Polyglot), việc cấu hình proxy riêng biệt cho từng công cụ (Git, Swift SPM, Docker, cURL, apt) đôi khi gây tốn công sức và dễ để sót các luồng mạng phụ.
Một phương án hiện đại đang được nhiều đội ngũ DevOps áp dụng là kỹ thuật định tuyến qua Giao diện mạng ảo (TUN Mode) ở Tầng 3 (Network Layer) thông qua các Network Engine. Thay vì thiết lập thủ công từng công cụ, bạn có thể sử dụng các ứng dụng điều hướng mạng chuyên dụng để chiếm quyền kiểm soát toàn cục.
Triển khai TUN mode với NasaCode để chiếm quyền điều khiển toàn cục:
nasacode up --mode tun
Khi kích hoạt lệnh trên, toàn bộ lưu lượng TCP và UDP phát sinh từ mọi tiến trình (Git, Swift SPM, Docker) sẽ tự động bị điều hướng vào đường hầm SOCKS5 ở cấp độ kernel mà không cần khai báo bất kỳ biến môi trường nào. Cách làm này giúp lược bỏ các bước cấu hình biến phức tạp và ngăn ngừa rủi ro rò rỉ mạng do sai sót cấu hình phần mềm.

Kỹ thuật định tuyến toàn cục qua giao diện mạng ảo (TUN Mode) gom toàn bộ lưu lượng TCP/UDP ở cấp độ Kernel mà không cần cấu hình biến môi trường thủ công.
Hardening (bảo mật nâng cao) & Troubleshooting
Để hệ thống duy trì tính ổn định lâu dài trong môi trường sản xuất, bạn cần áp dụng thêm các biện pháp củng cố an ninh và chuẩn bị phương án xử lý sự cố.
Giới hạn truy cập bằng UFW Allowlist và Fail2ban
Khi mở cổng 1080 trên Bastion Host, nguy cơ bị các công cụ tự động quét cổng luôn hiện hữu. Hãy kết hợp với các quy tắc Hardening bảo mật VPS Ubuntu 26.04 LTS bằng cách tàng hình SSH và cách ly AI Agent, đồng thời thiết lập tường lửa UFW theo nguyên tắc chỉ cấp quyền cho địa chỉ đáng tin cậy.
Thiết lập chính sách khóa mặc định và mở cổng cho IP của CI Runner:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow from IP_CI_RUNNER to any port 1080 proto tcp
sudo ufw enable
Để ngăn chặn các nỗ lực dò mật khẩu (brute-force), hãy cài đặt fail2ban. Tạo tập tin /etc/fail2ban/jail.d/dante.conf để giám sát nhật ký truy cập:
[danted]
enabled = true
port = 1080
protocol = tcp
filter = danted
logpath = /var/log/syslog
maxretry = 5
findtime = 600
bantime = 86400
Nếu có địa chỉ IP đăng nhập thất bại quá 5 lần trong 10 phút, Fail2ban sẽ tự động chặn IP đó trong 24 giờ.
Xử lý lỗi Timeout, rớt kết nối và Connection refused
Khi vận hành thực tế, pipeline có thể gặp một số hiện tượng kết nối không mong muốn. Dưới đây là cách khoanh vùng và khắc phục:
- Lỗi
Connection refused: Kiểm tra xem dịch vụ SOCKS5 có đang lắng nghe đúng giao diện mạng hay không bằng lệnh ss -tulpn | grep 1080. Nếu sử dụng UFW, hãy kiểm tra danh sách chặn thông qua sudo ufw status verbose.
- Hiện tượng rớt kết nối giữa chừng (Connection Dropped): Khi tải các gói dependency dung lượng lớn của Swift, nếu đường truyền không phát sinh dữ liệu liên tục, các thiết bị NAT trung gian có thể ngắt phiên TCP ở trạng thái rảnh rỗi. Việc bổ sung tùy chọn
ServerAliveInterval 60 trong cấu hình autossh sẽ gửi các gói tin giữ nhịp định kỳ mỗi phút, duy trì đường truyền luôn thông suốt.
Câu hỏi thường gặp (FAQ)
1. Tại sao biến môi trường HTTP_PROXY thường bị phớt lờ trong môi trường CI/CD?
Vì biến này chỉ hoạt động ở Tầng 7 (Application Layer). Các lệnh gọi hệ thống sử dụng giao thức SSH (như Git clone), UDP, hoặc TCP thô sẽ tự động bỏ qua nó. Bạn cần sử dụng proxy native của từng công cụ hoặc định tuyến qua TUN Mode.
2. Hiện tượng DNS Leak khi build code là gì và cách phòng tránh?
Là lỗi cấu hình khiến máy chủ tự phân giải tên miền tại mạng cục bộ thay vì qua proxy, gây rò rỉ metadata hoặc lỗi Cannot resolve host. Để phòng tránh, luôn sử dụng tiền tố socks5h:// để ép quá trình phân giải DNS diễn ra từ xa trên máy chủ proxy.
3. Dùng tham số --network=host có phải là giải pháp an toàn để cấu hình Proxy SOCKS5 cho CI/CD Pipeline chạy Docker không?
Không. Tham số này phá vỡ tính cô lập không gian mạng của container, gây rủi ro bảo mật. Hãy sử dụng file /etc/docker/daemon.json để cấp proxy cho tiến trình nền kéo image, và ~/.docker/config.json để cấp proxy cho môi trường build bên trong container.
4. Còn cần cài đặt proxychains4 để ép Swift 6.4 đi qua SOCKS5 nữa không?
Không cần thiết. Từ khi áp dụng đề xuất SE-0549, Swift Package Manager đã hỗ trợ native proxy. Bạn chỉ cần chạy lệnh swift package config set-proxy để định tuyến mạng tự động mà không phải can thiệp vào thư viện hệ điều hành.
5. Định tuyến TUN Mode (Tầng 3) khác biệt thế nào so với cấu hình proxy truyền thống?
Thay vì phải khai báo proxy lắt nhắt cho từng phần mềm (Git, Docker, SPM), TUN Mode tạo ra một card mạng ảo ở cấp độ Kernel. Nó tự động gom toàn bộ traffic TCP/UDP của hệ thống và đẩy vào đường hầm SOCKS5, giúp chống rò rỉ lưu lượng triệt để.
Kết luận
Triển khai Proxy SOCKS5 cho CI/CD Pipeline là một phương pháp tiếp cận giúp giải quyết các hạn chế về giới hạn tốc độ (rate-limit), bảo vệ thông tin hạ tầng nội bộ và tăng cường khả năng kiểm soát luồng phát hành phần mềm. Nhờ các tính năng hỗ trợ proxy trực tiếp trong hệ sinh thái Swift 6.4 cùng khả năng định tuyến linh hoạt của Docker, bạn hoàn toàn có thể xây dựng một hệ thống build khép kín, an toàn và dễ dàng bảo trì.
Đã đến lúc kiểm tra lại cấu trúc mạng trên các worker hiện tại của dự án. Bạn có thể bắt đầu bằng việc khởi tạo một job kiểm thử, áp dụng luồng SOCKS5 và dùng lệnh curl https://api.ipify.org qua proxy để xác nhận địa chỉ IP đại diện đã chuyển sang Bastion Host. Khi kiểm soát tốt lưu lượng đầu ra, quy trình triển khai ứng dụng sẽ luôn diễn ra thuận lợi vào mọi thời điểm.
Tài liệu tham khảo