Ngày đăng: 6 tháng 11 năm 2023
NAT, hay địa chỉ mạng, là một thuật ngữ chung để chỉ các mangling packets nhằm chuyển hướng chúng đến một địa chỉ thay thế. Thông thường, điều này được sử dụng để cho phép lưu lượng truy cập vượt qua ranh giới mạng. Một máy chủ triển khai NAT thường có quyền truy cập vào hai mạng trở lên và được định cấu hình để định tuyến lưu lượng giữa chúng.
Port forwarding (Chuyển tiếp cổng) là quá trình chuyển tiếp các yêu cầu cho một cổng cụ thể tới máy chủ, mạng hoặc cổng khác. Vì quá trình này sửa đổi đích đến của packet đang truyền nên nó được coi là một loại hoạt động NAT.
Trong hướng dẫn này, chúng tôi sẽ trình bày cách sử dụng iptables
để chuyển tiếp cổng tới máy chủ phía sau tường lửa bằng cách sử dụng kỹ thuật NAT. Điều này hữu ích nếu bạn đã định cấu hình một mạng riêng nhưng vẫn muốn cho phép một số lưu lượng truy cập nhất định bên trong thông qua một gateway machine được chỉ định.
Để làm theo hướng dẫn này, bạn sẽ cần:
sudo
. Bạn có thể tìm hiểu cách thực hiện việc này với bài viết của chúng tôi về hướng dẫn thiết lập máy chủ ban đầu Ubuntu 20.04. Có thể bỏ qua Bước 4 của hướng dẫn này vì chúng tôi sẽ thiết lập và định cấu hình tường lửa trong hướng dẫn này.iptables
để nó có thể hoạt động như máy chủ tường lửa (firewall server) của bạn. Bạn có thể thực hiện việc này bằng cách làm theo hướng dẫn của chúng tôi về Cách triển khai Tường lửa cơ bản với Iptables trên Ubuntu 20.04. Sau khi hoàn tất, máy chủ tường lửa của bạn sẽ có sẵn những thứ sau để sử dụng:
iptables-persistent
/etc/iptables/rules.v4
iptables
Máy chủ mà bạn thiết lập mẫu tường lửa trong đó sẽ đóng vai trò là tường lửa và bộ định tuyến cho mạng riêng của bạn. Với mục đích trình diễn, máy chủ thứ hai sẽ được cấu hình với một máy chủ web chỉ có thể truy cập được bằng giao diện riêng tư (Private Interface) của nó. Bạn sẽ định cấu hình firewall machine để chuyển tiếp các yêu cầu nhận được trên giao diện công cộng (Public Interface) của nó tới máy chủ web mà nó sẽ tiếp cận trên giao diện riêng tư.
Trước khi bắt đầu, bạn cần biết giao diện và địa chỉ nào đang được cả hai máy chủ của bạn sử dụng.
Để biết thông tin chi tiết về hệ thống của riêng bạn, hãy bắt đầu bằng cách tìm các giao diện mạng của bạn. Bạn có thể tìm thấy các giao diện trên máy của mình và các địa chỉ được liên kết với chúng bằng cách chạy như sau:
- ip -4 addr show scope global
Sample Output2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 203.0.113.1/18 brd 45.55.191.255 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 10.0.0.1/16 brd 10.132.255.255 scope global eth1
valid_lft forever preferred_lft forever
Đầu ra được đánh dấu hiển thị hai giao diện (eth0
và eth1
) và địa chỉ được gán cho mỗi giao diện (lần lượt là 203.0.113.1
và 10.0.0.1
). Để tìm ra giao diện nào trong số này là giao diện công cộng của bạn, hãy chạy lệnh này:
- ip route show | grep default
Outputdefault via 111.111.111.111 dev eth0
Thông tin giao diện từ đầu ra này (eth0
trong ví dụ này) sẽ là giao diện được kết nối với cổng mặc định của bạn. Đây gần như chắc chắn là giao diện công cộng của bạn.
Tìm các giá trị này trên mỗi máy của bạn và sử dụng chúng để làm theo phần còn lại của hướng dẫn này.
Để làm cho mọi thứ rõ ràng hơn, chúng tôi sẽ sử dụng các phép gán địa chỉ và giao diện trống sau đây trong suốt hướng dẫn này. Vui lòng thay thế các giá trị của riêng bạn bằng những giá trị được liệt kê sau đây:
Chi tiết mạng máy chủ web:
203.0.113.1
10.0.0.1
eth0
eth1
Chi tiết mạng tường lửa:
203.0.113.2
10.0.0.2
eth0
eth1
Bắt đầu kết nối với máy chủ web của bạn bằng cách đăng nhập bằng sudo
user của bạn.
Bước đầu tiên là cài đặt Nginx trên máy chủ lưu trữ web của bạn và khóa nó để nó chỉ nghe (listen) giao diện riêng tư của nó. Điều này sẽ đảm bảo rằng máy chủ web của bạn sẽ chỉ khả dụng nếu bạn thiết lập chuyển tiếp cổng chính xác.
Bắt đầu bằng cách cập nhật package cache cục bộ:
- sudo apt update
Tiếp theo sử dụng apt
để tải và cài đặt phần mềm:
- sudo apt install nginx
Sau khi Nginx được cài đặt, hãy mở tệp cấu hình khối máy chủ mặc định để đảm bảo rằng nó chỉ nghe giao diện riêng tư. Mở tệp bằng trình soạn thảo văn bản ưa thích của bạn. Ở đây chúng tôi sẽ sử dụng nano
:
- sudo nano /etc/nginx/sites-enabled/default
Bên trong, tìm chỉ thị listen
. Nó phải được liệt kê hai lần liên tiếp ở đầu cấu hình:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
. . .
}
Ở lệnh listen
đầu tiên, hãy thêm địa chỉ IP riêng của máy chủ web của bạn và dấu hai chấm trước số 80
để yêu cầu Nginx chỉ nghe trên giao diện riêng tư. Chúng tôi chỉ trình bày tính năng chuyển tiếp IPv4 trong hướng dẫn này, vì vậy bạn có thể xóa lệnh listen thứ hai được định cấu hình cho IPv6.
Tiếp theo, sửa đổi các chỉ thị listen
như sau:
server {
listen 10.0.0.1:80 default_server;
. . .
}
Lưu và đóng tập tin khi bạn hoàn tất. Nếu bạn đã sử dụng nano
, bạn có thể thực hiện việc này bằng cách nhấn CTRL + X
, sau đó là Y
và ENTER
.
Bây giờ hãy kiểm tra tệp để tìm lỗi cú pháp:
- sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Nếu không có lỗi ở đầu ra, hãy khởi động lại Nginx để kích hoạt cấu hình mới:
- sudo systemctl restart nginx
Tại thời điểm này, việc xác minh mức độ truy cập bạn có vào máy chủ web của mình là rất hữu ích.
Từ máy chủ tường lửa của bạn, hãy thử truy cập máy chủ web của bạn từ giao diện riêng tư bằng lệnh sau:
- curl --connect-timeout 5 10.0.0.1
Nếu thành công, kết quả đầu ra của bạn sẽ dẫn đến thông báo sau:
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
. . .
Nếu bạn cố gắng sử dụng giao diện công cộng, bạn sẽ nhận được thông báo cho biết nó không thể kết nối:
- curl --connect-timeout 5 203.0.113.1
Outputcurl: (7) Failed to connect to 203.0.113.1 port 80: Connection refused
Những kết quả này được mong đợi.
Bây giờ bạn sẽ tiến hành triển khai chuyển tiếp cổng trên firewall machine của mình.
Điều đầu tiên bạn cần làm là kích hoạt chuyển tiếp lưu lượng ở cấp kernel. Theo mặc định, hầu hết các hệ thống đều tắt tính năng chuyển tiếp.
Để bật chuyển tiếp cổng chỉ cho session này, hãy chạy như sau:
- echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
Output1
Để bật chuyển tiếp cổng vĩnh viễn, bạn sẽ phải chỉnh sửa tệp /etc/sysctl.conf
. Bạn có thể làm điều này bằng cách mở tệp với đặc quyền sudo
:
- sudo nano /etc/sysctl.conf
Trong tệp, tìm và bỏ ghi chú dòng có nội dung như sau:
net.ipv4.ip_forward=1
Lưu và đóng tập tin khi bạn hoàn tất.
Sau đó áp dụng các cài đặt trong tập tin này. Đầu tiên chạy lệnh sau:
- sudo sysctl -p
Outputnet.ipv4.ip_forward = 1
Sau đó chạy lệnh tương tự, nhưng thay thế cờ -p
bằng --system
:
- sudo sysctl --system
Output. . .
* Applying /usr/lib/sysctl.d/50-pid-max.conf ...
kernel.pid_max = 4194304
* Applying /etc/sysctl.d/99-cloudimg-ipv6.conf ...
net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.default.use_tempaddr = 0
* Applying /etc/sysctl.d/99-sysctl.conf ...
net.ipv4.ip_forward = 1
* Applying /usr/lib/sysctl.d/protect-links.conf ...
fs.protected_fifos = 1
fs.protected_hardlinks = 1
fs.protected_regular = 2
fs.protected_symlinks = 1
* Applying /etc/sysctl.conf ...
net.ipv4.ip_forward = 1
Tiếp theo, bạn sẽ định cấu hình tường lửa để lưu lượng truy cập vào giao diện công cộng (eth0
) trên cổng 80
sẽ được chuyển tiếp đến giao diện riêng tư (eth1
) của bạn.
Tường lửa mà bạn đã định cấu hình trong hướng dẫn Cách triển khai mẫu tường lửa cơ bản với Iptables trên Ubuntu 20.04 có chuỗi FORWARD
được đặt thành DROP
lưu lượng truy cập theo mặc định. Bạn cần thêm các quy tắc cho phép bạn chuyển tiếp kết nối đến máy chủ web của mình. Vì lý do bảo mật, bạn nên khóa mục này thật chặt để chỉ cho phép những kết nối bạn muốn chuyển tiếp.
Trong chuỗi FORWARD
, bạn sẽ chấp nhận các kết nối mới dành cho cổng 80
đến từ giao diện công cộng và chuyển sang giao diện riêng tư của bạn. Các kết nối mới được xác định bởi tiện ích mở rộng conntrack
và sẽ được biểu thị cụ thể bằng gói TCP SYN như sau:
- sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
Điều này sẽ cho phép packet đầu tiên, nhằm thiết lập kết nối, đi qua tường lửa. Bạn cũng cần phải cho phép mọi lưu lượng truy cập tiếp theo theo cả hai hướng bắt nguồn từ kết nối đó. Để cho phép lưu lượng ESTABLISHED
và RELATED
giữa giao diện công cộng và riêng tư của bạn, hãy chạy các lệnh sau. Đầu tiên cho giao diện công cộng của bạn:
- sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Sau đó, đối với giao diện riêng tư của bạn:
- sudo iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Kiểm tra kỹ xem chính sách của bạn trên chuỗi FORWARD
có được đặt thành DROP
không:
- sudo iptables -P FORWARD DROP
Tại thời điểm này, bạn đã cho phép một số lưu lượng truy cập nhất định giữa giao diện công cộng và riêng tư đi qua tường lửa của mình. Tuy nhiên, bạn chưa định cấu hình các quy tắc thực sự sẽ cho iptables
biết cách dịch và điều hướng lưu lượng truy cập.
Tiếp theo, bạn sẽ thêm các quy tắc sẽ cho iptables
biết cách định tuyến lưu lượng truy cập của bạn. Bạn cần thực hiện hai thao tác riêng biệt để iptables
thay đổi chính xác các packet để máy khách có thể giao tiếp với máy chủ web.
Hoạt động đầu tiên, được gọi là DNAT
, sẽ diễn ra trong chuỗi PREROUTING
của bảng nat
. DNAT
là một hoạt động thay đổi địa chỉ đích của packet để cho phép nó định tuyến chính xác khi nó đi qua giữa các mạng. Các máy khách trên mạng công cộng sẽ kết nối với máy chủ tường lửa của bạn và sẽ không biết về cấu trúc liên kết mạng riêng của bạn. Do đó, bạn cần thay đổi địa chỉ đích của từng packet để khi gửi đi trên mạng riêng của bạn, nó sẽ biết cách truy cập chính xác vào máy chủ web của bạn.
Vì bạn chỉ định cấu hình chuyển tiếp cổng và không thực hiện NAT trên mọi gói truy cập tường lửa của mình, nên bạn sẽ cần match cổng 80
theo quy tắc của mình. Bạn sẽ match các packet nhắm đến cổng 80
với địa chỉ IP riêng của máy chủ web của bạn (10.0.0.1
trong ví dụ sau):
- sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
Quá trình này xử lý một nửa toàn cảnh. Packet sẽ được định tuyến chính xác đến máy chủ web của bạn. Tuy nhiên, lúc này packet vẫn sẽ có địa chỉ gốc của máy khách làm địa chỉ nguồn. Máy chủ sẽ cố gắng gửi trả lời trực tiếp đến địa chỉ đó, điều này sẽ khiến việc thiết lập kết nối TCP hợp pháp không thể thực hiện được.
Để định cấu hình định tuyến phù hợp, bạn cũng cần sửa đổi địa chỉ nguồn của packet khi nó rời tường lửa trên đường đến máy chủ web. Bạn cần sửa đổi địa chỉ nguồn thành địa chỉ IP riêng của máy chủ tường lửa (10.0.0.2
trong ví dụ sau). Câu trả lời sau đó sẽ được gửi trở lại tường lửa, sau đó tường lửa có thể chuyển tiếp nó trở lại máy khách như mong đợi.
Để bật chức năng này, hãy thêm quy tắc vào chuỗi POSTROUTING
của bảng nat
, quy tắc này được đánh giá ngay trước khi các packet được gửi đi trên mạng. Bạn sẽ match các packet dành cho máy chủ web của mình theo địa chỉ IP và cổng:
- sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport 80 -d 10.0.0.1 -j SNAT --to-source 10.0.0.2
Khi quy tắc này được áp dụng, máy chủ web của bạn sẽ có thể truy cập được bằng cách trỏ trình duyệt web của bạn vào địa chỉ công khai của máy tường lửa:
- curl 203.0.113.2
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
. . .
Thiết lập chuyển tiếp cổng của bạn hiện đã hoàn tất.
Bây giờ bạn đã thiết lập chuyển tiếp cổng, bạn có thể lưu cổng này vào bộ quy tắc vĩnh viễn của mình.
Nếu bạn không quan tâm đến việc mất các nhận xét trong bộ quy tắc hiện tại của mình, hãy sử dụng lệnh netfilter-persistent
để sử dụng dịch vụ iptables
và lưu quy tắc của bạn:
- sudo service netfilter-persistent save
Output * Saving netfilter rules... run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
[ OK ]
Nếu bạn muốn giữ lại nhận xét trong tệp của mình, hãy mở nó lên và chỉnh sửa thủ công:
- sudo nano /etc/iptables/rules.v4
Bạn sẽ cần điều chỉnh cấu hình trong bảng filter
cho các quy tắc chuỗi FORWARD
đã được thêm vào. Bạn cũng sẽ cần điều chỉnh phần cấu hình bảng nat
để có thể thêm các quy tắc PREROUTING
và POSTROUTING
của mình. Nội dung sẽ giống như sau:
*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]
# Acceptable UDP traffic
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
# Acceptable ICMP traffic
# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP
# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# Rules to forward port 80 to our web server
# Web server network details:
# * Public IP Address: 203.0.113.1
# * Private IP Address: 10.0.0.1
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.2
# * Private IP Address: 10.0.0.2
# * Public Interface: eth0
# * Private Interface: eth1
-A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# End of Forward filtering rules
# Commit the changes
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Rules to translate requests for port 80 of the public interface
# so that we can forward correctly to the web server using the
# private interface.
# Web server network details:
# * Public IP Address: 203.0.113.1
# * Private IP Address: 10.0.0.1
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.2
# * Private IP Address: 10.0.0.2
# * Public Interface: eth0
# * Private Interface: eth1
-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
-A POSTROUTING -d 10.0.0.1 -o eth1 -p tcp --dport 80 -j SNAT --to-source 10.0.0.2
# End of NAT translations for web server traffic
COMMIT
*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
Lưu và đóng tệp sau khi bạn đã thêm nội dung và điều chỉnh các giá trị để phản ánh môi trường mạng của riêng bạn.
Tiếp theo, kiểm tra cú pháp của tệp quy tắc của bạn:
- sudo sh -c "iptables-restore -t < /etc/iptables/rules.v4"
Nếu không phát hiện thấy lỗi, hãy tải bộ quy tắc:
- sudo service netfilter-persistent reload
Output * Loading netfilter rules... run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start
[ OK ]
Bây giờ hãy kiểm tra xem máy chủ web của bạn vẫn có thể truy cập được thông qua địa chỉ IP công cộng của tường lửa hay không:
- curl 203.0.113.2
Điều này sẽ hoạt động giống như trước đây.
Bây giờ, bạn đã quen với việc chuyển tiếp cổng trên máy chủ Linux có iptables
. Quá trình này bao gồm việc cho phép chuyển tiếp ở cấp kernel, thiết lập quyền truy cập để cho phép chuyển tiếp lưu lượng của cổng cụ thể giữa hai giao diện trên hệ thống tường lửa, và định cấu hình quy tắc NAT để các packet có thể được định tuyến chính xác. Điều này có vẻ giống như một quá trình khó sử dụng, nhưng nó cũng thể hiện tính linh hoạt của packet filtering framework netfilter
và tường lửa iptables
. Điều này có thể được sử dụng để ngụy trang cấu trúc liên kết mạng riêng của bạn trong khi cho phép lưu lượng dịch vụ truyền tự do qua gateway firewall machine của bạn.