Đêm Hệ Thống Điện Thoại Sập
Đêm thứ Ba, 11:47 tối. Điện thoại tôi sáng lên — CEO gọi. “Toàn bộ đường dây điện thoại công ty sập hết rồi. Sáng mai 9 giờ mình có cuộc họp bán hàng với khách hàng lớn.” Tôi mở dashboard PBX thuê ngoài lên và thấy đúng cơn ác mộng quen thuộc: dịch vụ của nhà cung cấp hoàn toàn không truy cập được, không có ETA, hàng đợi ticket hỗ trợ tồn đọng ba ngày.
Đến cuối tuần sau, tôi đã có một PBX tự host hoạt động đầy đủ trên VPS $12/tháng — SIP trunk từ nhà cung cấp giá rẻ, extension nội bộ cho cả team, định tuyến cuộc gọi thực sự hợp lý. Cài đặt đó đã chạy production được 14 tháng. Thời gian downtime duy nhất: hai lần bảo trì theo lịch trên VPS.
Đây là cách làm lại y hệt như vậy.
Bạn Đang Xây Dựng Gì
Hãy hiểu rõ mô hình tổng thể trước khi chạm vào bất kỳ lệnh nào.
Asterisk là engine telephony mã nguồn mở — xử lý cuộc gọi, bridge âm thanh và dịch giao thức. Hãy coi nó như kernel của hệ thống điện thoại.
FreePBX là giao diện web bọc bên ngoài Asterisk. Không có nó, cấu hình Asterisk đồng nghĩa với việc chỉnh sửa tay các file .conf và hy vọng syntax đúng. FreePBX biến điều đó thành GUI tương đối dễ dùng được hỗ trợ bởi database.
Luồng cuộc gọi hoạt động như sau:
- SIP Trunk: Kết nối của bạn ra thế giới bên ngoài — nhà cung cấp VoIP cấp cho bạn một số điện thoại thật để định tuyến cuộc gọi vào server qua internet
- Extension: Số nội bộ (101, 102,…) được gán cho softphone hoặc điện thoại IP bàn trên mạng của bạn
- Dialplan: Quy tắc quyết định cuộc gọi đi đâu — cuộc gọi đến từ trunk chuyển đến extension 101, ring group hoặc menu IVR
VPS 1 vCPU/2 GB xử lý được khoảng 20–30 cuộc gọi G.711 đồng thời mà không bị quá tải. Đủ dùng thoải mái cho hầu hết các team nhỏ.
Yêu Cầu Trước Khi Bắt Đầu
- Một server Linux — Rocky Linux 9 hoặc Ubuntu 22.04 LTS, tối thiểu 1 vCPU và 1 GB RAM
- Địa chỉ IP public (hoặc IP private tĩnh nếu chỉ dùng trong LAN)
- Tài khoản SIP trunk — hướng dẫn này dùng VoIP.ms (tính phí theo phút, không cần hợp đồng, khoảng $0.009/phút cho cuộc gọi Mỹ)
- Quyền truy cập firewall để mở UDP 5060 (SIP) và UDP 10000–20000 (RTP audio)
Cài Đặt FreePBX
Mở các cổng firewall cần thiết trước. Asterisk cần chúng ngay khi khởi động, vì vậy hãy làm điều này trước khi chạy installer.
Trên Rocky Linux 9:
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=5060/udp
firewall-cmd --permanent --add-port=5061/tcp
firewall-cmd --permanent --add-port=10000-20000/udp
firewall-cmd --reload
Trên Ubuntu 22.04, cài đặt các dependency cốt lõi trước:
apt update && apt install -y \
git curl wget \
php8.1 php8.1-curl php8.1-xml php8.1-mysql php8.1-mbstring \
apache2 mariadb-server asterisk asterisk-config
systemctl enable --now asterisk mariadb apache2
Sau đó tải FreePBX installer và chạy:
cd /usr/src
wget http://mirror.freepbx.org/modules/_cache/freepbx-17.0-latest.tgz
tar xfz freepbx-17.0-latest.tgz
cd freepbx
./install -n
Quá trình cài đặt mất 10–15 phút. Khi hoàn tất, mở http://YOUR_SERVER_IP trên trình duyệt và chạy qua setup wizard. Đặt mật khẩu admin mạnh ngay bây giờ — trước khi làm bất cứ điều gì khác.
Khóa Chặt Ngay Lập Tức
Các scanner SIP sẽ tìm thấy server của bạn chỉ trong vài giờ sau khi nó lên mạng. Trong FreePBX GUI, vào Admin → System Admin → Intrusion Detection và bật tích hợp fail2ban. Nó tự động chặn các IP sau nhiều lần đăng ký thất bại liên tiếp, ngăn chặn hầu hết các cuộc tấn công toll-fraud tự động trước khi chúng kịp làm gì.
Cấu Hình SIP Trunk Đầu Tiên
Vào Connectivity → Trunks → Add Trunk → Add SIP (chan_pjsip) Trunk.
Với VoIP.ms, cấu hình trông như sau:
Trunk Name: voipms-main
=== Cài đặt chung ===
Username: your_voipms_username
Secret: your_voipms_password
SIP Server: denver.voip.ms # chọn POP gần nhất
SIP Port: 5060
=== Nâng cao (pjsip) ===
Authentication: Outbound
Registration: Send
Match Inbound Auth: Username
Sau khi lưu, mở Admin → Asterisk Logfiles và chú ý dòng:
Registered SIP 'voipms-main' at denver.voip.ms
Dòng đó có nghĩa là trunk đã hoạt động. Nếu thay vào đó bạn thấy Authentication failed, hãy kiểm tra hai điều: thông tin đăng nhập của bạn và liệu tài khoản VoIP.ms có sử dụng xác thực bằng username/password không. Xác thực dựa trên IP là tùy chọn kia, trong cài đặt “Authentication Type” của tài khoản — nếu tùy chọn đó đang bật, username/password sẽ không hoạt động.
Thêm Extension Nội Bộ
Mở Applications → Extensions → Add Extension → Add New PJSIP Extension.
Extension: 101
Display Name: Alice
Secret: dung-mat-khau-ngau-nhien-manh
Lặp lại cho từng người dùng. Sau đó cài softphone — Zoiper và MicroSIP (Windows) đều miễn phí, Linphone chạy được trên Linux — với cấu hình sau:
Domain/Server: YOUR_SERVER_IP
Username: 101
Password: mat-khau-ban-da-dat
Transport: UDP
Port: 5060
Sau khi đăng ký, các extension có thể gọi trực tiếp cho nhau bằng số. Không cần trunk, không tốn phí theo phút — cuộc gọi nằm hoàn toàn trong Asterisk.
Định Tuyến Cuộc Gọi Đến và Đi
Tuyến Cuộc Gọi Đến
Tuyến cuộc gọi đến nằm tại Connectivity → Inbound Routes → Add Incoming Route:
Description: Đường dây chính
DID Number: +15551234567 # số của bạn từ VoIP.ms
Destination: Extensions → 101
Cần xử lý ngoài giờ làm việc? Thêm Time Condition tại Applications → Time Conditions, rồi định tuyến cuộc gọi đến qua đó. Giờ làm việc chuyển đến extension 101, buổi tối chuyển vào voicemail.
Tuyến Cuộc Gọi Đi
Với cuộc gọi đi, vào Connectivity → Outbound Routes → Add Outbound Route:
Route Name: external-calls
Trunk Sequence: voipms-main
Mẫu quay số:
Match Pattern: NXXNXXXXXX # số Mỹ 10 chữ số
Match Pattern: 1NXXNXXXXXX # 11 chữ số có mã quốc gia
Áp dụng thay đổi, gọi một số bên ngoài từ extension 101 và xác nhận cuộc gọi thành công.
Gỡ Lỗi Âm Thanh Một Chiều (Vấn Đề Kinh Điển Lúc 2 Giờ Sáng)
Âm thanh một chiều là vấn đề phổ biến nhất khi tự host VoIP. Bạn nghe thấy người gọi nhưng họ không nghe được bạn — hoặc ngược lại. Gần như lúc nào cũng do NAT.
# Kết nối vào Asterisk CLI và theo dõi cuộc gọi trực tiếp
asterisk -rvvv
# Trong cuộc gọi, tìm các dòng RTP stream
# Cả send VÀ receive đều phải xuất hiện:
# [VERBOSE] RTP Packet send: ...
# [VERBOSE] RTP Packet received: ...
Cách khắc phục là cho Asterisk biết IP public của bạn. Trong FreePBX, vào Settings → Asterisk SIP Settings → General SIP Settings:
External IP: your.public.ip.here
Local Networks: 192.168.1.0/24 # subnet LAN của bạn
Không có điều này, server của bạn quảng bá IP private trong SDP offer. Phía remote cố gửi âm thanh đến địa chỉ private đó. Không có gì đến nơi.
Với vấn đề đăng ký trunk, kiểm tra trực tiếp từ CLI:
pjsip show registrations
# Kết quả phải hiển thị:
# voipms-main Registered denver.voip.ms:5060
Những Gì Nên Thêm Tiếp Theo
Hệ thống cơ bản đã đủ dùng. Bốn tính năng bổ sung này nên làm trước khi coi là sẵn sàng production:
- Ghi âm cuộc gọi: Bật cho từng extension trong cài đặt của mỗi extension. Bản ghi lưu tại
/var/spool/asterisk/monitor/và phát lại trực tiếp từ module recordings của FreePBX - SIP TLS + SRTP: Mã hóa tín hiệu (cổng 5061) và âm thanh giữa điện thoại và server — quan trọng cho bất kỳ extension nào kết nối từ bên ngoài văn phòng
- Backup theo lịch: Thiết lập tại Admin → Backup & Restore trước khi quên. Phải build lại FreePBX từ đầu mà không có backup là một buổi chiều đau khổ
- Cập nhật module: Kiểm tra hàng tháng qua Admin → Module Admin → Check Online. Server SIP tiếp xúc internet là mục tiêu đang bị nhắm đến — các bản vá bảo mật rất quan trọng
Tổng chi phí vận hành: khoảng $12/tháng cho VPS 2 vCPU/2 GB cộng thêm phí trunk theo phút. Một team gọi 2.000 phút/tháng trên VoIP.ms tốn khoảng $18 tất cả. Dịch vụ thuê ngoài mà nó thay thế chạy $180/tháng cố định. Và vẫn sập lúc nửa đêm trước cuộc gọi với khách hàng lớn. Cài đặt này thì không.

