Dùng iptables NAT thay thế cho reverse proxy

Hôm rồi một khách hàng thông báo website của họ cứ chập chờn, lúc vào được, lúc lại không. Tôi vào kiểm tra thì thấy web-server của họ hoàn toàn ổn, duy một điều coi log lại không thấy kết nối nào đến được web-server cả. Loay hoay một hồi, khách hàng mới báo cho biết rằng họ có sử dụng một con squid làm reverse proxy đứng trước web-server, mục đích là để cache lại static content.

Tôi vào kiểm tra con squid này thì phát hiện trong log của nó phun ra khá nhiều lỗi. Google cho biết đây là những lỗi khá nghiêm trọng và cũng có đưa ra vài giải pháp, nhưng do tôi không có nhiều kinh nghiệm với squid thành ra loay hoay mãi mà vẫn không sao giải quyết được.

Tôi quyết định tạm thời stop con squid này lại, tìm một giải pháp thay thế. Ban đầu tôi định sử dụng Apache để làm reverse proxy do tôi có nhiều kinh nghiệm với thằng này. Tuy vậy, giải pháp này khá mất thời gian mà con reverse proxy này cũng sẽ bị "kết liễu" trong vài ngày tới, nên tôi quyết định sử dụng chức năng NAT của iptables để làm luôn cho gọn.

Thú thật là rất lâu rồi tôi không đụng đến iptables, nên tôi cũng mất gần 15' coi tài liệu mới nhớ lại cách làm. Tôi ghi lại ở đây để sau này có gặp sự cố tương tự thì có cách giải quyết nhanh:

iptables -t nat -A PREROUTING -p tcp --dport 80 -d 1.1.1.1 -i eth0 -j DNAT --to 2.2.2.2:80

iptables -t nat -A POSTROUTING -p tcp --dport 80 -o eth0 -j SNAT --to 1.1.1.1

Ghi chú:

- 1.1.1.1 là IP address của eth0 trên reverse proxy, 2.2.2.2 là IP address của eth0 trên web-server.

- 2 lệnh này được chạy trên reverse proxy và chúng chỉ "redirect" traffic đến cổng 80, nếu bạn cần redirect traffic đến các cổng khác như 443 chẳng hạn, bạn phải thêm vào các lệnh tương ứng.

- Lệnh số 1 có tác dụng chuyển destination IP address (hence DNAT) của tất cả TCP packet đến cổng 80 của IP 1.1.1.1 thành cổng 80 của IP 2.2.2.2. Lệnh này nằm ở chain PREROUTING, nghĩa là nó được apply trước giai đoạn routing.

- Lệnh số 2 có tác dụng chuyển source IP address (hence SNAT) của tất cả TCP packet đi ra bằng đường eth0 có destination port là 80 thành 1.1.1.1. Lệnh này nằm ở chain POSTROUTING, nghĩa là nó được apply sau giai đoạn routing.

Giải thích:

1. client 3.3.3.3 gửi một packet (src=3.3.3.3, dst=1.1.1.1) đến reverse proxy 1.1.1.1

2. Lệnh thứ nhất sẽ chuyển packet này thành (src=3.3.3.3, dst=2.2.2.2).

3. Lệnh thứ hai sẽ chuyển packet này thành (src=1.1.1.1, dst=2.2.2.2).

3. Sau khi web-server 2.2.2.2 nhận được packet này, nó sẽ tạo ra một packet (src=2.2.2.2, dst=1.1.1.1) và gửi lại cho reverse proxy 1.1.1.1.

4. reverse proxy 1.1.1.1 sẽ nhìn vào NAT table của lệnh thứ hai để chuyển packet này thành (src=2.2.2.2, dst=3.3.3.3)

5. reverse proxy 1.1.1.1 tiếp tục nhìn vào NAT table của lệnh thứ nhất để chuyển packet này thành (src=1.1.1.1, dst=3.3.3.3)

6. reverse proxy 1.1.1.1 gửi packet (src=1.1.1.1, dst=3.3.3.3) lại cho client 3.3.3.3
14 comments