Bối cảnh: Khi nào doanh nghiệp cần Squid Proxy?
Mình bắt đầu tiếp xúc với Squid từ hồi còn làm sysadmin cho một công ty logistics. Lúc đó, bộ phận IT nhận khiếu nại từ HR rằng nhân viên đang xem YouTube trong giờ làm, bandwidth bị ngốn hết khiến các cuộc họp video call liên tục bị lag. Giải pháp lúc đó là dựng Squid Proxy — và nó xử lý xong trong vòng một buổi sáng.
Squid Proxy Server giúp bạn làm được những việc mà router thông thường không có:
- Kiểm soát truy cập theo domain: Chặn YouTube, Facebook, TikTok theo danh sách, hoặc chỉ cho phép whitelist các site cần thiết
- Kiểm soát theo giờ: Cho phép mạng xã hội trong giờ nghỉ trưa, chặn ngoài giờ đó
- Cache nội dung: Nhiều máy tải cùng file — chỉ ra Internet một lần, tiết kiệm đáng kể băng thông
- Audit log đầy đủ: Biết chính xác máy nào, IP nào đã vào website gì, lúc mấy giờ
- Ẩn IP nội bộ: Client ra Internet qua IP proxy, không lộ topology mạng nội bộ
Công ty mình vẫn còn vài con server chạy CentOS 7, và việc migrate sang AlmaLinux là bài toán mình đã xử lý. Nhưng với các server proxy ít tải, team vẫn chọn CentOS Stream 9 vì chu kỳ hỗ trợ rõ ràng và tương thích tốt với RHEL ecosystem. Bài này mình sẽ hướng dẫn dựng Squid từ đầu, bao gồm cả xử lý SELinux và firewalld — hai thứ hay làm junior developer đau đầu nhất khi mới tiếp cận RHEL/CentOS.
Cài đặt Squid trên CentOS Stream 9
Bước 1: Cập nhật hệ thống và cài đặt Squid
Bắt đầu bằng việc cập nhật hệ thống, sau đó cài Squid từ repo mặc định của CentOS Stream 9:
sudo dnf update -y
sudo dnf install squid -y
Kiểm tra version vừa cài:
squid -v
Kết quả trả về thông tin build, trong đó có dòng Squid Cache: Version 5.x.
Bước 2: Khởi động và enable service
sudo systemctl enable squid --now
sudo systemctl status squid
Nếu thấy Active: active (running) là ổn. Squid mặc định lắng nghe trên port 3128.
Cấu hình chi tiết Squid
Tạo file cấu hình gọn
File mặc định /etc/squid/squid.conf có đến ~7000 dòng comment. Mình thường backup rồi viết lại file cấu hình gọn hơn cho dễ quản lý:
sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.backup
sudo nano /etc/squid/squid.conf
Dán nội dung cấu hình chuẩn cho môi trường doanh nghiệp:
# ============================================================
# Squid Proxy - Enterprise Config
# CentOS Stream 9
# ============================================================
# Port lắng nghe
http_port 3128
# === ACL: Định nghĩa mạng nội bộ ===
acl localnet src 192.168.0.0/16
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
# ACL chuẩn
acl SSL_ports port 443
acl Safe_ports port 80 443 8080 8443 21 70 210 280 488 591 777
acl CONNECT method CONNECT
# === ACL: Danh sách domain bị chặn ===
acl blocked_sites dstdomain "/etc/squid/blocked_sites.txt"
# === Rules ===
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access deny blocked_sites
http_access allow localnet
http_access allow localhost
http_access deny all
# === Cache ===
cache_dir ufs /var/spool/squid 1024 16 256
maximum_object_size 50 MB
cache_mem 256 MB
# === Log ===
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
# Ẩn thông tin server
via off
forwarded_for off
httpd_suppress_version_string on
Tạo danh sách website bị chặn
sudo nano /etc/squid/blocked_sites.txt
Nội dung ví dụ:
.youtube.com
.facebook.com
.tiktok.com
.netflix.com
.instagram.com
Lưu ý: Dấu chấm . trước domain sẽ chặn cả subdomain — ví dụ .youtube.com chặn luôn www.youtube.com, m.youtube.com, music.youtube.com.
Cấu hình ACL theo giờ làm việc
Tình huống thực tế: cho phép mạng xã hội trong giờ nghỉ trưa (12h–13h), chặn ngoài khung giờ đó:
# Thêm vào squid.conf (trước phần Rules)
# Giờ làm việc: Thứ 2-6, 8h-12h và 13h-18h
acl working_hours time MTWHF 08:00-12:00
acl working_hours time MTWHF 13:00-18:00
# Giờ nghỉ trưa
acl lunch_break time MTWHF 12:00-13:00
# Domain mạng xã hội
acl social_media dstdomain .facebook.com .youtube.com .tiktok.com
# Rules áp dụng:
http_access deny social_media working_hours
http_access allow social_media lunch_break localnet
Cấu hình SELinux cho Squid
Đây là phần nhiều người bỏ qua và sau đó thắc mắc tại sao Squid không chạy được dù config đúng. SELinux trên CentOS Stream 9 mặc định ở chế độ Enforcing.
Kiểm tra trạng thái:
getenforce
# Kết quả: Enforcing
Squid cần một số quyền SELinux đặc biệt. Port 3128 đã được SELinux cho phép mặc định, nhưng nếu bạn muốn đổi sang port khác (ví dụ 8080):
# Thêm port 8080 vào policy squid_port_t
sudo semanage port -a -t squid_port_t -p tcp 8080
# Kiểm tra lại
sudo semanage port -l | grep squid
Nếu Squid cần kết nối đến các port không chuẩn (ví dụ upstream proxy), bật boolean này:
sudo setsebool -P squid_connect_any 1
Khi gặp lỗi permission denied và không rõ SELinux đang chặn gì, đây là cách debug nhanh:
# Xem audit log các denial gần nhất
sudo ausearch -c 'squid' --raw | audit2allow -M my-squid
# Apply policy vừa tạo
sudo semodule -i my-squid.pp
Cấu hình firewalld
Mở port 3128 để client trong mạng nội bộ kết nối được đến proxy:
# Dùng service squid có sẵn trong firewalld (tiện hơn)
sudo firewall-cmd --zone=internal --add-service=squid --permanent
# Hoặc mở port trực tiếp nếu thích
sudo firewall-cmd --zone=internal --add-port=3128/tcp --permanent
# Apply
sudo firewall-cmd --reload
# Kiểm tra zone internal
sudo firewall-cmd --zone=internal --list-all
Kiểm tra interface mạng nội bộ thuộc zone nào, và chuyển nó sang zone internal nếu cần:
# Xem interface nào đang ở zone nào
sudo firewall-cmd --get-active-zones
# Ví dụ eth1 là interface nội bộ
sudo firewall-cmd --zone=internal --add-interface=eth1 --permanent
sudo firewall-cmd --reload
Validate config và restart Squid
Luôn kiểm tra syntax trước khi restart — tránh trường hợp config sai làm service không khởi động được:
# Parse và kiểm tra config
sudo squid -k parse
# Không có lỗi → restart
sudo systemctl restart squid
Kiểm tra và Monitoring
Test proxy từ client
Từ máy client trong mạng nội bộ, dùng curl để test qua proxy (thay 192.168.1.100 bằng IP thực của máy chạy Squid):
# Test truy cập bình thường
curl -x http://192.168.1.100:3128 http://example.com -I
# Mong đợi: HTTP/1.1 200 OK
# Test chặn domain
curl -x http://192.168.1.100:3128 http://www.youtube.com -I
# Mong đợi: HTTP/1.1 403 Forbidden
Xem log real-time
Access log Squid ghi lại toàn bộ hoạt động — đây là nguồn thông tin chính để audit:
sudo tail -f /var/log/squid/access.log
Mỗi dòng log có dạng:
1720123456.789 1234 192.168.1.50 TCP_MISS/200 5432 GET http://example.com/ - DIRECT/93.184.216.34 text/html
- 1720123456.789: Unix timestamp
- 1234: Thời gian xử lý (milliseconds)
- 192.168.1.50: IP client
- TCP_MISS/200: Cache miss, server trả HTTP 200
- GET http://example.com/: Phương thức và URL đầy đủ
Xem thống kê Squid
# Thống kê tổng quan
sudo squidclient -h localhost mgr:info
# Cache hit rate
sudo squidclient -h localhost mgr:counters | grep -i hit
Script tìm top domain truy cập nhiều nhất
Hữu ích khi cần báo cáo hàng tuần cho quản lý:
#!/bin/bash
# Top 10 domain truy cập nhiều nhất trong log hiện tại
cat /var/log/squid/access.log | \
awk '{print $7}' | \
sed 's|http[s]*://||' | \
cut -d'/' -f1 | \
sort | uniq -c | \
sort -rn | \
head -10
Cấu hình log rotation
Môi trường nhiều user, log Squid có thể phình lên vài GB sau vài ngày. Cấu hình logrotate để tự dọn:
sudo nano /etc/logrotate.d/squid
/var/log/squid/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
postrotate
/usr/sbin/squid -k rotate
endscript
}
Xử lý lỗi thường gặp
Squid không start — lỗi permission:
# Kiểm tra SELinux có đang chặn không
sudo ausearch -m avc -ts recent | grep squid
# Debug nhanh: tạm set permissive (CHỈ để test, không dùng production)
sudo setenforce 0
sudo systemctl restart squid
# Nếu chạy được → vấn đề là SELinux → dùng audit2allow để fix đúng cách
sudo setenforce 1
Client không kết nối được qua proxy:
# Squid đang listen port nào?
sudo ss -tlnp | grep squid
# Firewall có đang block không?
sudo firewall-cmd --list-all --zone=internal
# Thử telnet từ client đến proxy
telnet 192.168.1.100 3128
Sau khi dựng Squid xong và hệ thống chạy ổn định, bước tiếp theo mình thường làm là chuyển sang transparent proxy — client không cần cấu hình proxy thủ công, mọi traffic HTTP tự động đi qua Squid nhờ iptables redirect. Nhưng đó là câu chuyện phức tạp hơn, cần kết hợp thêm SSL bump để inspect HTTPS traffic — để dành cho bài khác.

