banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận mạng và thiết bị mạng PF (Packet Filter) trên OpenBSD  XML
  [Article]   PF (Packet Filter) trên OpenBSD 31/01/2010 16:02:32 (+0700) | #1 | 204284
C0pyl3ft
Locked

[Minus]    0    [Plus]
Joined: 10/01/2010 23:36:27
Messages: 83
Offline
[Profile] [PM]
Tác giả: Someone ???
(Bài này sưu tầm được, không tìm thấy thông tin gì về tác giả của bài viết)

1. Tổng quan

Chúng ta biết, Internet là nơi tập trung rất nhiều host kết nối với nhau. Có một điều quan trọng cần phải quan tâm khi gia nhập các hệ thống mạng là làm cách nào để đảm bảo sự kết nối này luôn được an toàn. Một trong những phương pháp nhằm nâng cao tính an toàn của hệ thống mạng là lọc và loại bỏ các gói tin tiềm ẩn nguy cơ mất an toàn. Hệ tường lửa (firewall) được thiết kế cho mục tiêu đó, chúng hoạt động dựa trên các “chính sách” được thiết lập bởi người dùng.

Một hệ tường lửa có thể bao gồm một số thành phần. Trong đó, thành phần quan trọng nhất chính là trình lọc gói. Trình lọc gói có thể hỗ trợ trạng thái để việc ra quyết định chính xác hơn. Trạng thái trong các hệ tường lửa lọc gói giúp hệ thống theo dõi được các kết nối đã khởi tạo và so sánh với các gói tin liên quan đến kết nối đó. Trong khi một hệ tường lửa không hỗ trợ trạng thái chỉ căn cứ duy nhất vào nội dung của gói tin để ra quyết định. PF là một hệ tường lửa có hỗ trợ trạng thái tích hợp vào OpenBSD 3.0 và nó được sử dụng rất rộng rãi trên các hệ điều hành BSD nhờ tính hiệu quả và hiệu năng đã được công nhận.

2. Lịch sử ra đời

Hệ tường lửa PF (Packet Filter) trên OpenBSD, ngày nay thường được gọi đơn giản là là PF, được viết nhằm tạo ra một môi trường lọc dòng truyền thông TCP/IP nhanh và mạnh bởi Daniel Hartmeier và một số nhà phát triển OpenBSD vào giữa mùa hè và mùa thu năm 2001. Nó đã trở thành một phần mặc định trên hệ điều hành OpenBSD v3.0 từ tháng 12 năm 2001.

Sự cần thiết phải có một hệ tường lửa mới cho OpenBSD được đưa ra bởi một bài viết của Darren Reed. Vào thời điểm đó, IPFilter là hệ tường lửa duy nhất được tích hợp vào OpenBSD đã không hoàn toàn ban hành theo giấy phép BSD, điều này gây ra sự khó khăn trong việc phát triển hệ điều hành OpenBSD. IPFilter sau đó đã bị loại bỏ khỏi OpenBSD vào ngày 29/05/2001, sau thời điểm đó OpenBSD không hề có một hệ tường lửa nào được tích hợp sẵn. May mắn thay, Daniel Hartmeier (người Thụy Sỹ) đã thực hiện một số thử nghiệm về việc phát triển nhân hệ điều hành này. Anh ta bắt đầu đưa vào một số tính năng nhỏ vào phần mã ngăn xếp mạng và đưa các gói tin đi qua đó, sau đó anh ta đã nghĩ ra một cơ chế lọc gói dạng này. Và rồi PF đã ra đời từ đó, chính xác là nó được đưa vào OpenBSD vào 19:48:58 UTC ngày 24 tháng 6 năm 2001. Vài tháng sau đó, PF đã được tích hợp vào OpenBSD 3.0 như là một hệ lọc gói hoàn chỉnh hỗ trợ cả NAT.

Từ khi đưa ra PF, Daniel Hartmeier và nhóm phát triển trước đó đã là những người có kiến thức rất sâu về IPFilter. Trong bối cảnh này, Daniel đã đưa ra một bài báo trên USENIX 2002 công bố về các lần thử nghiệm hiệu năng để chứng minh rằng PF tích hợp vào OpenBSD 3.0 có hiệu năng không hề thua kém, thậm chí là tốt hơn, IPFilter hay những hệ tường lửa khác như iptables trên Linux. Ngoài ra, đã có một số thử nghiệm khác được thực thi với PF trên OpenBSD 3.0 và các phiên bản sau đó. Kết quả cho thấy PF thực sự là một hệ lọc gói hiệu quả. Có thể xem thêm bài viết của Daniel Hartmeier tại địa chỉ http://www.benzedrine.cx/pf-paper.html để có thông tin chi tiết hơn.

3. Tư tưởng thiết kế

PF là một hệ tường lửa hỗ trợ trạng thái được tích hợp vào nhân hệ điều hành, nó kiểm tra các gói tin IP đi qua ngăn xếp mạng để đưa ra một trong các quyết định sau:

- Pass: Cho phép gói tin đi qua với sự sửa đổi hoặc không sửa đổi nội dung gói tin.
- Block: Khóa và loại bỏ hoàn toàn gói tin mà không có bất cứ thông báo nào.
- Reject: Từ chối nhận gói tin với một phản hồi, chẳng hạn như gửi một gói TCP reset cho bên gửi.
Việc ra quyết định dựa vào hai nhân tố là nội dung gói tin và thông tin có trong bảng trạng thái.

4. Quy tắc lọc gói

Tất cả gói tin sẽ được so sánh với tập quy tắc lọc gói. Tập quy tắc này bao gồm nhiều quy tắc được liên kết với nhau. Mỗi quy tắc bao gồm một tập tham số để quyết định xem gói tin dạng nào sẽ được quy tắc này áp dụng. Các tham số này có thể dựa trên địa chỉ nguồn và đích của gói tin, dựa trên giao thức, số hiệu cổng,...Nếu một gói tin thỏa mãn một quy tắc thì chỉ có một trong ba quyết định được đưa ra là hoặc gói tin sẽ được cho đi qua, hoặc gói tin sẽ bị loại bỏ mà không có phản hồi nào hoặc gói tin bị từ chối kèm theo một thông báo về nơi đã gửi gói tin đến.
Xét trong toàn tập quy tắc, gói tin sẽ được kiểm tra theo từng quy tắc với thứ tự từ trên xuống dưới. PF hoạt động theo nguyên tắc quy tắc cuối cùng thỏa mãn là quy tắc sẽ quyết định hành động của gói tin. Nghĩa là trong một tập quy tắc, có thể gói tin thỏa mãn nhiều quy tắc nhưng quy tắc thỏa mãn cuối cùng mới là quy tắc quyết định.

5. Bảng trạng thái

Một hệ tường lửa hỗ trợ trạng thái nói lên rằng hệ tường lửa đó không chỉ căn cứ vào bản thân nội dung gói tin mà còn theo dõi được mối kết nối đến nơi gói tin đó xuất phát. Khi có bất cứ quy tắc nào cho phép gói tin đi qua được thỏa mãn thì nó sẽ tạo ra một mục trạng thái trong bảng trạng thái. Trước khi thực hiện lọc một gói tin thì bảng trạng thái sẽ được sử dụng để so sánh với gói tin, nếu gói tin đó xuất phát từ nơi hiện đang duy trì một kết nối trong bảng trạng thái thì nó sẽ được cho qua mà không cần so sánh với quy tắc nào cả.

Đối với các gói TCP, trạng thái được thực hiện bằng cách kiểm tra các số thứ tự của các window, điều này giúp chống lại các tấn công dựa trên số thứ tự của gói tin. Các gói tin UDP về bản chất là không hỗ trợ trạng thái. Hai gói tin UDP sẽ được coi là thuộc cùng một kết nối nếu địa chỉ nơi gửi và cổng thỏa mãn một mục trạng thái nào đó. Các gói tin ICMP thì có thể rơi vào một trong hai loại. Nếu là một gói tin ICMP error thì nó phải kết hợp với một kết nối nào đó nằm trong bảng trạng thái còn gói ICMP query và ICMP reply tự tạo cho chúng những trạng thái riêng giống như trường hợp của UDP.

PF lưu trữ các mục trạng thái trong một cây AVL. Một cây AVL là một cây tìm kiếm nhị phân cân bằng. Vật chứa này cung cấp khả năng tìm kiếm rất hiệu quả và có thể mở rộng cây rất tốt. Một vật chứa dạng như bảng băm có thể vẫn cung cấp khả năng tìm kiếm tốt. Tuy nhiên, về bản chất là chúng bị cố định về kích thước. Nếu số lượng thành viên tăng sẽ xẩy ra hiện tượng xung đột khi trùng giá trị băm.

6. NAT (Network Address Translation)

NAT thường được sử dụng để cho phép các host với dãi địa chỉ IP dành riêng chia sẻ cùng một địa chỉ IP có khả năng định tuyến công khai. NAT được tích hợp sẵn trong PF, mỗi mục NAT trong PF thực chất là một quy tắc trong PF và được ánh xạ với bảng trạng thái. Điều này nâng cao đáng kể hiệu năng thực thi cho hệ tường lửa.
Bảng trạng thái bao gồm các ba cặp địa chỉ/cổng: internal, gateway và external. Có hai cây chứa các khóa, một được sắp xếp dựa trên cặp internal và external, một được sắp xếp dựa trên cặp external và gateway. Điều này cho phép không những tìm kiếm một trạng thái thỏa mãn dòng truyền thông đi ra và đi vào mà còn cung cấp khả năng ánh xạ NAT vào cùng thời điểm mà không cần phải tìm kiếm thêm thông tin. PF cũng hỗ trợ việc chuyển tiếp theo cổng và chuyển hướng kết nối. Một trình chuyển tiếp tầng ứng dụng như ftp-proxy có thể cho phép chạy các trình FTP phía sau NAT.

7. Tính năng bình thường hóa (Normalization)

Tính năng này sẽ giúp giải quyết vấn đề trong sáng hóa dòng truyền thông IP. Lấy ví dụ, các hệ điều hành sẽ thực hiện việc giải quyết việc trùng lặp khi phân mảnh các gói tin theo nhiều cách khác nhau. Một số giữ nguyên dữ liệu cũ trong khi số khác lại thay thế dữ liệu cũ bằng dữ liệu mới hơn. Đối với các hệ thống sử dụng các gói tin phân mảnh mới hơn thay cho gói tin cũ thì nó phải ghi lại giá trị header của giao thức trước khi chúng chuyển đến cho firewall để xử lý.
Trên OpenBSD, không hề tồn tại lỗ hổng để có các tấn công dựa vào cơ chế phân mảnh gói tin. Tất cả gói tin phân mảnh đều được đưa vào bộ đệm và tái tạo bởi PF vì thế nếu có xung đột xẩy ra giữa các gói trùng nhau thì sẽ được giải quyết trước khi đưa gói tin đến đích nhận.

8. Khả năng điều chỉnh số thứ tự

PF có thể theo dõi các số thứ tự của gói tin và thêm một số thứ tự ngẫu nhiên vào tất cả số hiệu gói tin của một kết nối. Điều này giúp bảo vệ các host tránh được tất công khi bộ tạo số thứ tự yếu.

9. Ghi nhật ký

Cơ chế ghi nhật ký của PF dựa trên BPF, nó thực hiện ghi vào một giao diện mạng ảo gọi là pflog0. Điều này cho phép tất cả ứng dụng giám sát mạng có thể giám sát được nhật ký của PF với sự sửa đổi tối thiểu nhất. Có thể dùng tcpdump để giám sát nhật ký theo thời gian thực và áp dụng các bộ lọc khác để hiển thị các gói tin được áp dụng.
[Up] [Print Copy]
  [Article]   PF (Packet Filter) trên OpenBSD 31/01/2010 16:06:45 (+0700) | #2 | 204285
C0pyl3ft
Locked

[Minus]    0    [Plus]
Joined: 10/01/2010 23:36:27
Messages: 83
Offline
[Profile] [PM]
1.1 Kích hoạt PF và tệp cấu hình

1.1.1 Kích hoạt PF
Để kích hoạt PF và thiết lập nó đọc tệp cấu hình vào thời điểm khởi động hãy thêm dòng sau vào tệp /etc/rc.conf.local.

Code:
pf=YES


Cần khởi động lại hệ thống để thiết lập mới có hiệu lực. Ngoài ra, có thể kích hoạt PF theo cách thủ công bằng cách sử dụng tiện ích pfctl:

Code:
# pfctl -e
# pfctl -d


Trong đó, tùy chọn –e dùng để kích hoạt PF, -d dùng để tắt PF. Chú ý là khi bật hay tắt, PF không thực hiện việc nạp tập quy tắc mới mà chúng ta phải nạp tập quy tắc bằng một lệnh khác trước hoặc sau khi PF được bật.

Code:
1.1.2 Tệp cấu hình của PF


PF đọc thông tin cấu hình từ tệp /etc/pf.conf vào thời điểm khởi động, nó được nạp bởi các kịch bản rc. Chú ý là trong khi /etc/pf.conf là tệp mặc định được nạp bởi các tệp kịch bản rc của hệ thống thì vẫn có thể có các tệp văn bản khác được nạp vào phiên dịch bởi trình pfctl sau đó chèn vào PF. Đối với một số ứng dụng, các tập quy tắc có thể được nạp từ các tệp khác nhau vào thời gian khởi động. Giống như bất kỳ một ứng dụng nào thiết kế trên Unix, PF cho phép cách cấu hình hết sức mềm dẻo. Tệp cấu hình của PF bao gồm bảy thành phần sau:

- Biến toàn cục (Macro): Các biến do người dùng định nghĩa dùng để diễn đạt các địa chỉ IP, tên giao tiếp mạng,…
- Bảng (Table): Một cấu trúc được sử dụng để lưu trữ một danh sách địa chỉ IP.
- Thuộc tính (Option): Một số thuộc tính dùng để điều khiển cách thức hoạt động của PF.
- Bình thường hóa (Scrup): Việc xử lý lại gói tin nhằm bình thường hóa và phân mảnh gói tin.
- Hàng đợi (Queueing): Cho phép điều khiển băng thông và thiết lập quyền ưu tiên cho gói tin.
- Chuyển đổi địa chỉ (Translation): Điều khiển việc chuyển đổi địa chỉ và chuyển hướng gói tin.
- Quy tắc lọc gói (Filter rule): Các quy tắc cho phép lọc hoặc loại bỏ gói tin khi chúng đi qua bất kỳ giao tiếp mạng nào.
Ngoại trừ Macro và Table, các thành phần khác thường xuất hiện theo thứ tự từ trên xuống dưới nhưng không phải tệp cấu hình nào cho PF cũng có đầy đủ tất cả các thành phần trên. Trong một tệp cấu hình các dòng trống sẽ bị bỏ qua khi phân tích, các dòng bắt đầu bằng ký hiệu # được coi là nội dung chỉ dẫn và cũng được bỏ qua.
1.2 Tiện ích điều khiển PF

Sau khi khởi động, PF có thể được quản lý bởi trình pfctl. Sau đây là một vài ví dụ về việc sử dụng công cụ này:
Code:
# pfctl -f /etc/pf.conf     Nạp tệp cấu hình pf.conf
# pfctl -nf /etc/pf.conf    Phân tích tệp cấu hình nhưng không nạp
# pfctl -Nf /etc/pf.conf    Chỉ nạp các quy tắc NAT của tệp cấu hình
# pfctl -Rf /etc/pf.conf    Chỉ nạp các quy tắc lọc gói của tệp cấu hình
# pfctl -sn                 Hiển thị các quy tắc NAT hiện tại 
# pfctl -sr                 Hiển thị các quy tắc lọc gói hiện tại
# pfctl -ss                 Hiển thị bảng trạng thái hiện tại
# pfctl -si                 Hiển thị thống kê và bộ đếm lọc gói
# pfctl -sa                 Hiển thị tất cả thông tin về PF


Để có danh sách chi tiết về cách sử dụng lệnh này hãy tham khảo trang man của pfctl.

1.3 Danh sách và Macro

1.3.1 Danh sách (list)

Danh sách cho phép đưa ra nhiều thành phần có tiêu chí giống nhau vào một quy tắc. Chẳng hạn một danh sách có thể bao gồm nhiều giao thức, số hiệu cổng, địa chỉ,…Thay vì đưa mỗi thành phần thuộc danh sách vào một quy tắc thì chỉ cần viết một quy tắc và đưa tên danh sách vào quy tắc đó. Danh sách được tạo ra bằng cách đưa các thành phần vào giữa hai dấu ngoặc nhọn {…}. Khi PF đọc tệp cấu hình, nếu gặp danh sách nó sẽ phiên dịch mỗi thành phần thuộc danh sách ra một quy tắc để thực thi. Lấy ví dụ chúng ta có quy tắc chứa danh sách sau:

Code:
block out on fxp0 from { 192.168.0.1, 10.5.32.6 } to any


Sẽ được mở rộng thành hai quy tắc
Code:
block out on fxp0 from 192.168.0.1 to any
block out on fxp0 from 10.5.32.6 to any


Có thể đưa nhiều danh sách vào một quy tắc và không chỉ giới hạn ở quy tắc lọc gói mà có thể đưa vào các dạng quy tắc khác.

Code:
rdr on fxp0 proto tcp from any to any port { 22 80 } -> 192.168.0.6
block out on fxp0 proto { tcp udp } from { 192.168.0.1, 10.5.32.6 } \
to any port { ssh telnet }

Chú ý dấu phẩy giữa các mục trong danh sách là tùy chọn. Một danh sách có thể chứa một danh sách khác, chẳng hạn như:
Code:
trusted = "{ 192.168.1.2 192.168.5.36 }"
pass in inet proto tcp from { 10.10.0.0/24 $trusted } to port 22


Có thể sử dụng ký hiệu phủ định giống như dạng dưới đây, tuy nhiên không cho phép sử dụng hai lần phủ định.
Code:
pass in on fxp0 from { 10.0.0.0/8, !10.1.2.3 }


Quy tắc trên nói lên rằng cho tất cả dòng truyền thông đi qua fxp0 có địa chỉ xuất phát từ dãi 10.0.0.0/8 ngoại trừ địa chỉ 10.1.2.3. Quy tắc này có thể được mở rộng thành hai quy tắc sau:
Code:
pass in on fxp0 from 10.0.0.0/8
pass in on fxp0 from !10.1.2.3


Nếu sử dụng nhiều thành phần thì nên thay thế danh sách bởi bảng.

1.3.2 Biến toàn cục (Macro)


Macro là các biến toàn cục do người dùng định nghĩa dùng để diễn tả các địa chỉ IP, số hiệu cổng, tên giao tiếp mạng,… Macro giúp giảm bớt tính phức tạp của các quy tắc PF và giúp cho việc duy trì tập quy tắc dễ dàng hơn. Tên của Macro phải bắt đầu bằng một chữ cái và có thể bao gồm chữ cái, chữ số cùng dấu gạch dưới. Không được chứa các từ như pass, out, queue trong tên macro.
Code:
ext_if = "fxp0"
block in on $ext_if from any to any


Hai dòng trên tạo ra một macro có tên là ext_if và được sử dụng bởi một quy tắc lọc gói. Khi định nghĩa xong một macro, để tham chiếu đến nó hãy sử dụng ký hiệu $.

Có thể xác định giá trị cho Macro ở dạng danh sách và có thể định nghĩa macro theo cách đệ quy.
Code:
friends = "{ 192.168.1.1, 10.0.2.5, 192.168.43.53 }"

host1 = "192.168.1.1"
host2 = "192.168.1.2"
all_hosts = "{" $host1 $host2 "}"


1.4 Bảng (Table)

1.4.1 Giới thiệu

Một bảng được sử dụng để nhóm các địa chỉ IPv4 hoặc IPv6 với nhau. Việc tìm kiếm trên bảng được thực hiện rất nhanh chóng và nó chiếm ít bộ nhớ hơn danh sách. Vì lý do này, bảng là ý tưởng tốt cho việc lưu trữ một nhóm lớn các địa chỉ, khi tìm kiếm một bảng lưu trữ 50,000 địa chỉ mất thời gian lâu hơn tìm kiếm một bảng 50 địa chỉ không đáng kể. Bảng có thể sử dụng cho các mục đích sau:

- Làm địa chỉ nguồn hoặc đích cho các quy tắc lọc gói, scrub, NAT và chuyển hướng gói.
- Dùng trong các quy tắc NAT.
- Dùng trong các quy tắc chuyển hướng gói tin
- Dùng làm địa chỉ đích trong các thuộc tính của quy tắc lọc như route-to, reply-to và dup-to.
Bảng có thể được tạo và đưa vào tệp pf.conf thông qua tiện ích pfctl.

1.4.2 Cấu hình

Trong tệp pf.conf, bảng được tạo ra bằng các chỉ dẫn cho bảng. Các thuộc tính sau có thể được chỉ định cho bảng:
- Const: Nội dung của bảng không thể thay đổi khi bảng đã được tạo ra. Khi thuộc tính này không được xác lập thì lệnh pfctl có thể thêm hoặc loại bỏ các địa chỉ trong bảng vào bất kỳ thời điểm nào trừ khi chạy securelevel ở mức 2 hoặc cao hơn.
- Persist: Ra dấu cho nhân lưu trữ bảng trong bộ nhớ kể cả khi không có quy tắc nào tham chiếu đến nó. Thông thường, nhân sẽ tự động loại bỏ bảng nếu tất cả quy tắc tham chiếu đến nó đã bị giải phóng.

Code:
table <goodguys> { 192.0.2.0/24 }
table <rfc1918> const { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table <spammers> persist
block in on fxp0 from { <rfc1918>, <spammers> } to any
pass  in on fxp0 from <goodguys> to any

Các địa chỉ có thể được sử dụng kèm theo dấu phủ định dạng như:
Code:
table <goodguys> { 192.0.2.0/24, !192.0.2.5 }


Dòng trên nói lên rằng bảng googguys chứa tất cả địa chỉ nằm trong dãi 192.0.2.0/24 ngoại từ địa chỉ 192.0.2.5. Chú ý là tên bảng bao giờ cũng phải nằm trong hai dấu ngoặc nhọn < >.
Ngoài ra, có thể đưa nội dung một tệp văn bản chứa các địa chỉ IP vào một bảng
Code:
table <spammers> persist file "/etc/spammers"
block in on fxp0 from <spammers> to any


Trong đó, tệp /etc/spammers có thể chứa một danh sách các địa chỉ IP hoặc chứa các khối địa chỉ mạng dạng CIDR, mỗi thành phần nằm trên một dòng. Tất cả các dòng bắt đầu bằng # sẽ bị bỏ qua khi phân tích tệp này.
1.4.3 Dùng pfctl để thao tác với bảng
Bảng có thể được thao tác bằng cách sử dụng lệnh pfctl. Chẳng hạn, để thêm mới một mục vào bảng

<spammers> chúng ta dùng lệnh sau:Code:
# pfctl -t spammers -T add 218.70.0.0/16


Lệnh trên sẽ tạo ra bảng <spammers> nếu nó chưa tồn tại. Để liệt kê các địa chỉ của bảng này có thể dùng lệnh:
Code:
# pfctl -t spammers -T show

Thuộc tính –v có thể dùng kết hợp với –T để hiển thị thông tin thống kê trên mỗi mục của bảng. Để loại bỏ các địa chỉ khỏi bảng sử dụng lệnh sau:

Code:
# pfctl -t spammers -T delete 218.70.0.0/16


Để có thêm thông tin về cách thao tác với bảng hãy tham khảo trang man của pfctl.

1.4.4 Xác định địa chỉ

Ngoài cách đưa địa chỉ vào bảng có thể sử dụng tên trạm (hostmane). Khi đưa tên trạm vào bảng thì nó sẽ được phân giải thành địa chỉ IP. Ngoài ra, địa chỉ IP cũng có thể được xác định bằng cách nhập vào tên của giao tiếp mạng hợp lệ hoặc các từ khóa của nó. Khi đó, bảng sẽ chứa tất cả địa chỉ IP xác định cho giao tiếp mạng này (kể các các địa chỉ loopback). Một trong những giới hạn khi chỉ định địa chỉ là bảng không cho phép đưa vào địa chỉ dạng 0.0.0.0/0 hoặc 0/0. Trong trường hợp này phải đưa trực tiếp vào quy tắc hoặc sử dụng macro.
1.4.5 Kiểm tra địa chỉ
Một phép tìm kiếm trên bảng sẽ cho kết quả là các mục thỏa mãn chặt chẽ nhất. Có thể tạo một bảng dạng như:

Code:
table <goodguys> { 172.16.0.0/16, !172.16.1.0/24, 172.16.1.100 }
block in on dc0 all
pass  in on dc0 from <goodguys> to any


Trong đó, tất cả gói tin đi qua dc0 đều có địa chỉ nguồn thỏa mãn bảng <goodguys>. Chúng ta hãy xét các trường hợp ví dụ về địa chỉ nguồn của gói tin:
- 172.16.50.5 là một dãi nằm trong 172.16.0.0/16 nên gác gói tin có địa chỉ này sẽ được cho qua.
- 172.16.1.25 nằm trong dãi 172.16.1.0/24 tuy nhiên các dãi này được xác định bởi dấu ! nên gói tin có địa chỉ này sẽ bị cấm. Ngoại trừ gói tin có địa chỉ 172.16.1.100 được đi qua.
- 10.1.4.55 là địa chỉ không nằm trong bảng nên sẽ bị cấm
[Up] [Print Copy]
  [Article]   PF (Packet Filter) trên OpenBSD 31/01/2010 16:17:00 (+0700) | #3 | 204286
C0pyl3ft
Locked

[Minus]    0    [Plus]
Joined: 10/01/2010 23:36:27
Messages: 83
Offline
[Profile] [PM]
1.5 Cơ chế lọc gói

1.5.1 Giới thiệu


Lọc gói là cơ chế lựa chọn việc cho qua hay khóa các gói dữ liệu khi chúng đi qua một giao tiếp mạng. Các tiêu chí mà PF căn cứ để ra quyết định dựa trên thông tin thu được từ header ở Lớp 3 (IPv4 và IPv6), Lớp 4 (TCP, UDP, ICMP và ICMP6). Các tiêu chí thông dụng vẫn là địa chỉ, cổng đích và nguồn, giao thức mạng được sử dụng.
Một quy tắc lọc gói chỉ ra các tiêu chí mà một gói tin phải thỏa mãn rồi đưa ra quyết định là nó sẽ bị khóa hoặc cho qua khi gói tin thỏa mãn tất cả tiêu chí đưa ra bởi quy tắc. Tập quy tắc được kiểm tra theo thứ tự từ trên xuống dưới. Trừ khi gói tin thỏa mãn một quy tắc nào đó nếu không nó sẽ được kiểm tra đối chiếu với tất cả quy tắc theo chiều từ trên xuống dưới cho đến quy tắc cuối cùng và sẽ được quyết định bởi quy tắc này. Trong quá trình kiểm tra, quy tắc cuối cùng thỏa mãn sẽ được áp dụng. Nếu không có quy tắc nào thỏa mãn thì quy tắc cuối cùng sẽ được áp dụng.

1.5.2 Cú pháp của một quy tắc

Cú pháp tổng quát nhất của một quy tắc có dạng sau:

Code:
action [direction] [log] [quick] [on interface] [af] [proto 
protocol] \
   [from src_addr [port src_port]] [to dst_addr [port dst_port]] \
   [flags tcp_flags] [state]


Trong đó:
Tham số Diễn giải
action Hành động thực hiện khi các gói tin thỏa mãn tiêu chí đặt ra, khóa hoặc cho qua. Một hành động cho qua nghĩa là sẽ đưa gói tin quay về kernel để xử lý tiếp còn hành động khóa là loại bỏ hoặc loại bỏ gói tin nhưng có phản hồi về nguồn gửi.
direction Chuyển hướng gói tin nghĩa là chuyển gói tin đến một giao tiếp mạng nào đó, có thể theo chiều đi ra hoặc đi vào.
log Chỉ định rằng sẽ ghi lại thông tin nhật ký bằng pflog nếu gói tin thỏa mãn quy tắc, nếu quy tắc này tạo ra một trạng thái thì chỉ có gói tin làm kiến tạo trạng thái mới có thể được ghi nhật ký. Để ghi nhật ký tất cả gói tin hãy sử dụng thuộc tính log(all).
quick Nếu một gói tin thỏa mãn quy tắc có thuộc tính quick thì đây được xem là quy tắc cuối cùng cần kiểm tra và hệ thống sẽ áp dụng luôn hành động của quy tắc này lên gói tin.
interface Tên hoặc nhóm giao tiếp mạng mà gói tin đi qua. Các giao tiếp mạng có thể được thêm vào các nhóm tùy chọn sử dụng lệnh ifconfig. Một số nhóm sau được tự động tạo ra bởi nhân:
- Nhóm egress chứa các giao tiếp mạng đang đóng vai trò là default gateway.
- Các nhóm giả lập như ppp hoặc carp.
if Nhóm địa chỉ của gói tin, thông thường tham số inet (ipv4) hoặc inet6 (ipv6) sẽ được sử dụng để xác định tham số này dựa trên địa chỉ nguồn/đích của gói tin.
protocol Giao thức ở lớp 4 bao gồm: tcp, udp, icmp, icmp6, các giao thức có số hiệu từ 0 đến 255, các giao thức liệt kê trong tệp /etc/protocols và các giao thức được dùng trong các danh sách xác định trước.
src_addr, dst_addr Địa chỉ IP nguồn/đích xác định bởi IP Header của gói tin.
src_port, dst_port Cổng nguồn/đích xác định bởi header của giao thức ở Lớp 4.
tcp_flags Cờ hiệu TCP,
state Xác định việc có lưu giữ trạng thái hay không. Có các dạng thiết lập trạng thái sau:
- keep state: Lưu giữ trạng thái với tất cả gói tin TCP, UDP và ICMP đây là thiết lập mặc định.
- modulate state: chỉ có hiệu lực với TCP, PF sẽ tạo ra một số ISN (Initial Sequence Numbers) cho các gói tin thỏa mãn quy tắc.
- synproxy state: Chuyển tiếp các kết nối TCP để bảo vệ máy chủ khỏi các tấn công TCP SYN flood. Tùy chọn này đã bao gồm cả hai tùy chọn trên.

Các tham số trong cú pháp của quy tắc lọc gói

1.5.3 Thiết lập cấm theo mặc định


Một khuyến cáo trong việc thực thi các hệ tường lửa là thiết lập cho hệ tường lửa này mặc định sẽ khóa tất cả dòng truyền thông. Lý do là nếu chúng ta ban đầu khóa tất cả dòng truyền thông sau đó chỉ lựa chọn cho qua một số dòng truyền thông sẽ giúp tránh được việc bỏ sót các ngăn chặn cần thiết. Để thiết lập điều này trong PF là khá đơn giản, chỉ cần thêm hai quy tắc sau vào cuối tập quy tắc:

Code:
block in  all
block out all

Hai quy tắc trên sẽ khóa tất cả dòng truyền thông theo mặc định đối với mọi nguồn xuất phát và đối với mọi hướng.

1.5.4 Dòng truyền thông được qua

Khi bạn đã thiết lập mặc định cấm tất cả dòng truyền thông như trên thì bước tiếp theo là phải tạo ra các quy tắc cho phép một số dòng truyền thông xác định đi qua. Sau đây là một số ví dụ:

Code:
# Pass traffic in on dc0 from the local network, 192.168.0.0/24,
# to the OpenBSD machine's IP address 192.168.0.1. Also, pass the
# return traffic out on dc0.
pass in  on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# Pass TCP traffic in on fxp0 to the web server running on the
# OpenBSD machine. The interface name, fxp0, is used as the
# destination address so that packets will only match this rule if
# they're destined for the OpenBSD machine.
pass in on fxp0 proto tcp from any to fxp0 port www


1.5.5 Sử dụng thuộc tính quick


Như đã đề cập ở phần trên, mỗi gói tin được so sánh với các quy tắc theo chiều từ trên xuống dưới cho đến quy tắc cuối cùng và quy tắc cuối thỏa mãn điều kiện sẽ được áp dụng. Có một ngoại lệ là sử dụng thuộc tính quick, khi đó nếu gói tin thỏa mãn quy tắc dạng này sẽ được áp dụng hành động ngay lập tức và bỏ qua tất cả các quy tắc sau nó. Hãy xét một ví dụ:

Code:
block in on fxp0 proto tcp from any to any port ssh
pass  in all


Chúng ta thấy, khi so sánh gói tin với hai quy tắc này có thể gói tin thỏa mãn quy tắc thứ nhất nhưng nó sẽ không bao giờ được áp dụng vì quy tắc thứ hai là quy tắc được xét sau mà gói tin có chiều đi vào luôn thỏa mãn, như vậy quy tắc thứ hai sẽ được áp dụng.
Nếu chúng ta thêm thuộc tính quick thì quy tắc thứ nhất sẽ được áp dụng khi gói tin thỏa mãn quy tắc này:
Code:
block in quick on fxp0 proto tcp from any to any port ssh
pass  in all


1.5.6 Lưu giữ trạng thái

Một trong những khả năng quan trọng của PF là “lưu giữ trạng thái” hay “thẩm tra trạng thái”. Đây là khả năng theo dõi trạng thái hoặc tiến trình của một kết nối mạng. Bằng cách lưu thông tin về mỗi kết nối vào bảng trạng thái, PF có thể nhanh chóng xác định được một gói tin gửi đến có thuộc về một kết nối đã thiết lập trước đó hay không, nếu nó thuộc về kết nối đã có thì sẽ được cho qua ngay lập tức mà không cần xét đến các quy tắc. Việc lưu giữ trạng thái có rất nhiều lợi ích như giúp cho tập quy tắc tường lửa đơn giản hơn, nâng cao hiệu năng của hệ thống.

Khi gói tin đầu tiên thỏa mãn một quy tắc thì sẽ tạo ra một mục trạng thái trong bảng trạng thái, mục trạng thái này sẽ lưu thông tin về nơi gửi và nơi nhận. Sau đó tất cả gói tin qua lại giữa hai thành phần này sẽ được áp dụng hành động của quy tắc đó mà không cần so sánh với tập quy tắc. Hệ PF triển khai trên OpenBSD trước 4.1 yêu cầu thiết lập việc lưu trạng thái với từng quy tắc, từ OpenBSD 4.1 trở đi, mặc định tất cả quy tắc đều lưu trạng thái với các gói tin thỏa mãn đầu tiên.

Đối với OpenBSD từ trước 4.1, để lưu giữ trạng thái cần chỉ rõ trong quy tắc:

Code:
pass out on fxp0 proto tcp from any to any keep state


Từ OpenBSD 4.1 trở về sau, mặc định tất cả quy tắc đều lưu giữ trạng thái:

Code:
pass out on fxp0 proto tcp from any to any


Quy tắc trên sẽ cho phép tất cả dòng truyền thông TCP đi ra trên giao tiếp mạng fxp0 và cũng cho phép dòng truyền thông trả lời ngược lại đi qua PF.

Ngoài việc lưu trữ trạng thái, PF còn cho phép điều chỉnh nội dung gói tin, khi đó một số Initial Sequence Number (ISN) sẽ được thêm vào các gói tin đi ra khỏi PF. Điều này giúp chống các tấn công lên các hệ thống sử dụng hệ điều hành có bộ tạo số ISN với độ ngẫu nhiên thấp. Ví dụ sau là một quy tắc thực hiện việc lưu giữ trạng thái của các gói tin TCP, UDP và ICMP đồng thời sửa đổi số TCP ISN:
Code:
pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state


Một điểm lợi khác của việc lưu trạng thái là các dòng ICMP thích hợp cũng có thể đi qua PF nhờ vào trạng thái. Lấy ví dụ, nếu một kết nối TCP cho phép đi qua thì nếu có các gói ICMP với địa nguồn thỏa mãn trạng thái này cũng sẽ được cho qua.

1.5.7 Lưu giữ trạng thái với UDP


Chúng ta thường nghe nói rằng “Không thể lưu giữ trạng thái với các kết nối UDP vì UDP là một giao thức không hỗ trợ trạng thái”. Điều này đúng, một phiên kết nối UDP không có khái niệm về trạng thái (không thể xác định nơi bắt đầu và kết thúc kết nối) nhưng không có nghĩa là PF không thể tạo ra trạng thái cho các kết nối UDP. Với các giao thức không thể xác định các gói tin bắt đầu và gói tin kết thúc thì PF chỉ đơn giản là lưu giữ lại thông tin về thời gian mà gói tin thỏa mãn quy tắc được đi qua. Nếu quá thời gian này thì trạng thái sẽ bị loại bỏ. Giá trị thời gian tới hạn được xác lập trong tệp pf.conf.

1.5.8 Các thuộc tính trạng thái

Khi tạo ra trạng thái, PF có thể cho phép thiết lập một số thuộc tính cho mục trạng thái, bao gồm:
Thuộc tính Diễn giải

max number Giới hạn số lượng mục trạng thái cho một quy tắc. Nếu đạt đến một số tối đa về mục trạng thái thì kể cả khi các gói tin thỏa mãn quy tắc vẫn không thể tạo ra mục trạng thái mới, khi đó phải chờ cho số lượng mục trạng thái giảm đi mới có thể tạo ra các trạng thái mới.
no state Không cho phép quy tắc tự động tạo trạng thái.
source-track Thuộc tính này cho phép theo dõi số lượng trạng thái tạo bởi mỗi địa chỉ IP nguồn. Có hai dạng xác định như sau:

- source-track rule: Số lượng trạng thái tối đa tạo ra bởi quy tắc này sẽ bị giới hạn bởi thuộc tính max-src-nodes và max-src-states. Chỉ các trạng thái được tạo bởi quy tắc này là được tính để so sánh với số lượng được giới hạn bởi quy tắc.
- source-track global: Số trạng thái tạo bởi tất cả quy tắc sử dụng thuộc tính này sẽ bị giới hạn. Mỗi quy tắc sẽ xác định các giá trị cho thuộc tính max-src-nodes và max-src-states khác nhau, tuy nhiên số mục trạng thái tổng tạo bởi tất cả quy tắc sẽ không vượt quá một số cho trước. Tổng số địa chỉ IP nguồn được theo dõi một cách tổng thể và kiểm soát bởi thuộc tính src-nodes.
max-src-nodes number Khi thuộc tính source-track được sử dụng thì max-src-nodes sẽ giới hạn số lượng địa chỉ IP có thể cùng lúc tạo ra trạng thái.
max-src-states number Khi thuộc tính source-track được sử dụng thì max-src-states sẽ giới hạn số lượng các mục trạng thái có thể tạo ra cùng một lúc đối vói mỗi địa chỉ IP nguồn. Phạm vi của sự giới hạn (các trạng thái chỉ tạo bởi quy tắc này hoặc các trạng thái tạo bởi tất cả quy tắc sử dụng source-track) phụ thuộc vào giá trị xác định cho source-track.
max-src-conn number Giới hạn số lượng tối đa các kết nối TCP cùng lúc dạng thực hiện đầy đủ bắt tay ba bước theo TCP mà một trạm đơn thực hiện.
max-src-conn-rate number / interval Giới hạn tỷ lệ các kết nối mới trên một đơn vị thời gian. Cả hai thuộc tính này sẽ tự động tuân theo thuộc tính source-track và không tương thích với thuộc tính source-track global.
overload <table> Đưa địa chỉ IP của trạm vào bảng.
flush [global] Loại bỏ tất cả trạng thái thỏa mãn quy tắc đã được tạo ra theo một IP nguồn xác định nào đó.
Các thuộc tính của bảng trạng thái

1.5.9 Các cờ TCP

Việc xác định các gói tin TCP có thỏa mãn quy tắc hay không dựa trên cờ TCP là cách thường dùng của các trình lọc gói TCP khi mở một kết nối mới. Các cờ TCP bao gồm:
Cờ TCP Diễn giải
F FIN - Finish: Kết thúc phiên truyền thông
S SYN - Synchronize: Tạo ra một yêu cầu bắt đầu phiên
R RST – Reset: Loại bỏ kết nối
P PUSH - Push: Gửi gói tin đi ngay lập tức
A ACK – Acknowlegement: Báo hiệu đã nhận được
U URG - Urgent
E ECE – Explicit Congestion Notification Echo
W CWR - Congestion Window Reduced

Để PF xét đến các cờ TCP thì từ khóa sau cần phải sử dụng trong tệp cấu hình:

flags check/mask
flags any

Thuộc tính check/mask cho PF biết là chỉ xét các giá trị cờ trên các gói tin có địa chỉ trong header thỏa mãn giá trị đặt ra. Thuộc tính any nghĩa là thực hiện xét giá trị cờ trên mọi gói tin. Ví dụ:
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
Quy tắc trên cho phép các gói tin TCP đi qua nếu cờ SYN được thiết lập và có cờ ACK tương ứng.

1.5.10 TCP SYN Proxy

Thông thường, khi trình khách khởi tạo một kết nối TCP đến trình chủ thì PF sẽ chuyển các gói tin bắt tay ba bước từ trình khách sang trình chủ. Thế nhưng PF có khả năng làm trung gian cho quá trình bắt tay ba bước này. Nó có thể đứng ra bắt tay với trình khách sau đó tạo ra một kết nối bắt tay với trình chủ, cuối cùng sẽ chuyển các gói tin giữa trình khách và trình chủ. Lợi ích của việc này là trước khi trình khách hoàn thành việc bắt tay sẽ không có bất cứ gói tin nào được chuyển đến trình chủ cả nhờ đó các tấn công dạng TCP SYN flood sẽ bị hạn chế do trình khách không thể bắt tay trực tiếp với trình chủ. Để sử dụng tính năng này thì từ khóa synproxy state được đưa vào các quy tắc, ví dụ:
Code:
pass in on $ext_if proto tcp from any to $web_server port www \
   flags S/SA synproxy state


Với quy tắc trên, các kết nối đến trình chủ web sẽ được PF chuyển tiếp TCP SYN, khi chọn thuộc tính này thì mặc định hai thuộc tính keep state và modulate state cũng được chọn. Chú ý là tính năng chuyển tiếp TCP SYN không hoạt động nếu PF chạy ở chế độ bridge.

1.5.11 Khóa các gói tin giả mạo

Giả mạo địa chỉ là trường hợp một người dùng ác ý đưa một địa chỉ IP nguồn vào các gói tin mà họ gửi đến đích nhằm che dấu địa chỉ IP thật nhằm đóng giả một đối tượng khác trên mạng. Một ai đó có thể giả mạo địa chỉ nhằm thực hiện các cuộc tấn công vào hệ thống mạng mà vẫn che dấu được nguồn gốc tấn công hoặc nhằm truy cập một dịch vụ nào đó chỉ cho phép một số dãi địa chỉ IP xác định.
PF cho phép việc chống lại sự giả mạo địa chỉ bằng cách sử dụng từ khóa antispoof như sau:
Code:
antispoof [log] [quick] for interface [af]


Trong đó:
- log: nếu có sự giả mạo xẩy ra thì ghi nhật ký bằng pflogd.
- quick: Nếu gói tin thỏa mãn quy tắc này thì quy tắc sẽ được thực thi và bỏ qua các qui tắc khác.
- interface: Giao tiếp mạng tại đó kích hoạt thuộc tính chống giả mạo địa chỉ, đây có thể là danh sách các giao tiếp mạng.
- af: Địa chỉ IPv4 hoặc IPv6.
Ví dụ:
Code:
antispoof for fxp0 inet


1.5.12 Chuyển tiếp đường dẫn unicast


Từ phiên bản OpenBSD 3.0, PF đưa vào tính năng Unicast Reverse Path Forwarding (uRPF). Khi một gói tin chạy ở chế độ có kiểm tra uRPF thì địa chỉ IP nguồn của gói tin được tìm kiếm trong bảng định tuyến. Nếu ở chiều ra thấy giao tiếp mạng trùng với chiều vào của gói tin thì thuộc tính uRPF sẽ đánh dấu cho qua. Nếu địa chỉ của của các giao tiếp mạng không trùng nhau thì đây có thể là hiện tượng giả mạo địa chỉ nguồn. Phép kiểm tra uRPF có thể được thực hiện bằng cách sử dụng từ khóa urpf-failed trong các quy tắc:
Code:
block in quick from urpf-failed label uRPF


uRPF cung cấp cơ chế gần giống các quy tắc antispoof.

1.5.13 Phát hiện hệ điều hành


Passive OS Fingerprinting (OSFP) là một phương pháp thụ động để phát hiện hệ điều hành nơi gói tin xuất phát dựa vào các đặc tính của gói tin TCP SYN. Thông tin này sau đó có thể được sử dụng như một tiêu chí trong các quy tắc lọc gói. PF xác định hệ điều hành bằng cách so sánh các đặc tính của gói tin TCP SYN với một tệp lưu dấu (mặc định là tệp /etc/pf.os). Khi PF được bật thì có thể xem nội dung tệp này bằng lệnh:

Code:
# pfctl -s osfp


Trong một quy tắc lọc gói, dấu hiệu của hệ điều hành có thể được chỉ ra bởi loại hệ điều hành, phiên bản, ... Sau đây là ví dụ về quy tắc có xét đến hệ điều hành:Code:
pass  in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown


1.5.14 Các thuộc tính IP


Mặc định, PF sẽ khóa tất cả gói tin với thuộc tính IP được thiết lập. Điều này có thể gây khó khăn cho các tiện ích phát hiện hệ điều hành như nmap. Nếu chúng ta có các ứng dụng yêu cầu cho qua các gói tin dạng này, chẳng hạn như IGMP, thì có thể thêm vào chỉ dẫn allow-opts như sau:
Code:
pass in quick on fxp0 all allow-opts


1.5.15 Một ví dụ về tập quy tắc lọc gói
Ví dụ sau đưa ra một tập quy tắc lọc gói sử dụng cho PF với các quy tắc thường dùng nhất.

Code:
ext_if  = "fxp0"
int_if  = "dc0"
lan_net = "192.168.0.0/24"
# table containing all IP addresses assigned to the firewall
table <firewall> const { self }
# don't filter on the loopback interface
set skip on lo0
# scrub incoming packets
scrub in all
# setup a default deny policy
block all
# activate spoofing protection for all interfaces
block in quick from urpf-failed
# only allow ssh connections from the local network if it's from the
# trusted computer, 192.168.0.15. use "block return" so that a TCP RST is
# sent to close blocked connections right away. use "quick" so that this
# rule is not overridden by the "pass" rules below.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
   to $int_if port ssh
# pass all traffic to and from the local network.
# these rules will create state entries due to the default
# "keep state" option which will automatically be applied.
pass in  on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net
# pass tcp, udp, and icmp out on the external (Internet) interface. 
# tcp connections will be modulated, udp/icmp will be tracked
# statefully.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# allow ssh connections in on the external interface as long as they're
# NOT destined for the firewall (i.e., they're destined for a machine on
# the local network). log the initial packet so that we can later tell
# who is trying to connect. use the tcp syn proxy to proxy the connection.
# the default flags "S/SA" will automatically be applied to the rule by
# PF.
pass in log on $ext_if proto tcp from any to ! <firewall> port ssh synproxy state


1.6 Chuyển đổi địa chỉ (NAT)


1.6.1 Giới thiệu

NAT (Network Address Translation) là cách ánh xạ một địa chỉ (hoặc mạng) thành một địa IP. NAT là cần thiết khi số lượng địa chỉ IP được ISP chỉ định nhỏ hơn số máy tính cần truy cập ra mạng bên ngoài. NAT đuợc mô tả trong RFC 1631, “The IP Network Address Translator (NAT)”. NAT cho phép sử dụng các dãi địa chỉ IP dành riêng để kết nối ra Internnet. Để thực thi NAT thì hệ thống phải có ít nhất 2 giao tiếp mạng.

1.6.2 Cách làm việc của NAT


Khi một trình khách ở một mạng bên trong muốn kết nối với một máy chủ trên internet, nó sẽ gửi các gói tin với địa chỉ đích là địa chỉ của máy chủ. Các gói tin này chứa tất cả thông tin về địa chỉ cần thiết để nó có thể tới đích được. NAT sẽ căn cứ vào các thuộc tính sau với các gói tin này:
- Địa chỉ IP nguồn (ví dụ 192.168.1.35)
- Cổng nguồn TCP hoặc UDP (ví dụ 2132)
Khi các gói tin đi qua thiết bị NAT chúng sẽ bị sửa đổi để bên ngoài tưởng như gói tin đó bản thân xuất phát từ thiết bị NAT này. Thiết bị NAT sẽ ghi nhớ lại các thay đổi đã tạo ra vào một bảng nhằm a) chuyển đổi ngược khi gói tin được trả về, b) đảm bảo rằng các gói tin quay về sẽ được đưa qua tường lửa mà không bị khóa. Chẳng hạn, NAT sẽ thực hiện các thay đổi sau:
- Thay đổi địa chỉ IP nguồn của gói tin bằng địa chỉ IP của giao tiếp mạng kết nối với bên ngoài (ví dụ là 24.5.0.5).
- Thay đổi cổng nguồn bằng một số ngẫu nhiên, thường là một số hiệu cổng không sử dụng đến (chẳng hạn như 53136).
Cả máy khách bên trong và máy chủ ngoài internet đều không hề biết được sự thay đổi này. Đối với máy chủ bên trong thì thiết bị NAT chỉ đơn giản là một Internet gateway. Đối với máy chủ trên Internet thì chúng hiểu các gói tin xuất phát từ thiết bị NAT, nó không hề biết đến sự tồn tại của máy khách ở các mạng bên trong thiết bị NAT.
Khi máy chủ trên Internet phản hồi lại các gói tin cho máy bên trong, chúng sẽ gửi đến địa chỉ đích là địa chỉ giao tiếp mạng bên ngoài của thiết bị NAT (24.5.0.5) tại cổng đã gửi gói tin (53136). Thiết bị NAT sẽ tìm trong bảng trạng thái để xác định xem các gói tin phản hồi có thỏa mãn một kết nối đã thiết lập nào đó không. Sẽ có một kết nối duy nhất thỏa mãn dựa trên cặp IP/cổng cho phép thiết bị NAT gửi gói tin về máy khách có địa chỉ 192.168.1.35 của mạng bên trong. Tiếp đến, thiết bị NAT sẽ thực hiện thay đổi giá trị của địa chỉ/cổng của gói tin phù hợp rồi gửi đến cho máy khách. Quá trình này dường như được thực hiện trong suốt với máy khách như khi máy khách gửi trực tiếp gói tin đến máy chủ trên Internet. Đối với các gói tin ICMP thì quá trình thực hiện cũng hoàn toàn tương tự chỉ khác ở việc không có sự sửa đổi cổng nguồn của gói tin.

1.6.3 NAT và cơ chế lọc gói


Việc chuyển đổi các gói tin vẫn phải qua bộ lọc gói và vẫn có thể bị khóa hoặc cho qua dựa trên các quy tắc lọc gói. Chỉ có một điểm khác là khi sử dụng kết hợp từ khóa pass vào luôn trong các quy tắc NAT. Khi đó sẽ cho phép các gói tin NAT đi qua bộ máy lọc gói. Cũng cần nắm được rằng khi chuyển đổi địa chỉ xẩy ra trước lọc gói thì bộ máy lọc gói sẽ xem xét gói đã được chuyển đổi dựa trên địa chỉ IP và cổng đã được chuyển đổi. Vì thế cần thiết lập các quy tắc lọc gói tương ứng với dải địa chỉ đã chuyển đổi bởi NAT.

1.6.4 Chuyển tiếp IP


Do NAT là cách thường được sử dụng trên các thiết bị định tuyến và thiết bị đóng vai trò gateway nên nó cần phải có tính năng chuyển tiếp IP làm sao để các gói tin có thể chuyển qua lại giữa các giao tiếp mạng trên một máy. Cơ chế chuyển tiếp IP được bật bằng tiện ích sysctl như sau:

Code:
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1 (if using IPv6)


Để thay đổi này có hiệu lực lâu dài có thể thêm hai dòng sau vào tệp /etc/sysctl.conf:
Code:
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1


Hai dòng này mặc định được đánh dấu # ở đầu dòng khi cài đặt hệ điều hành, hãy loại bỏ hai dấu # để chúng có hiệu lực.

1.6.5 Cấu hình NAT

Cú pháp của một quy tắc NAT có dạng tổng quát như sau:
Code:
nat [pass] [log] on interface [af] from src_addr [port src_port] to \
   dst_addr [port dst_port] -> ext_addr [pool_type] [static-port]


Trong đó:
Từ khóa Diễn giải
pass Cho phép các gói tin NAT đi qua
log Ghi nhật ký khi có gói tin thỏa mãn quy tắc, mặc định PF chỉ ghi nhật ký khi có gói tin thỏa mãn đầu tiên, để ghi nhật ký với mọi gói tin chọn log(all).
interface Giao tiếp mạng tại đó thực hiện NAT
af Kiểu địa chỉ, inet cho IPv4 và inet6 cho IPv6. PF thường xác định thông tin này dựa vào địa chỉ IP nguồn/đích.
src_addr Địa chỉ nguồn
Src_port Cổng nguồn
dst_addr Địa chỉ đích
dst_port Cổng đích
ext_addr Địa chỉ bên ngoài, là địa chỉ chuyển đổi bởi NAT
pool_type Xác định kiểu pool địa chỉ sử dụng khi chuyển đổi
static-port Ra hiệu cho PF không thay đổi cổng nguồn của gói tin TCP hoặc UDP
Các thuộc tính của quy tắc NAT
Sau đây là một số ví dụ về quy tắc NAT
Code:
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5


Quy tắc này thực hiện NAT trên giao tiếp mạng tl0 đối với tất cả gói tin đến từ dãi 192.168.1.0/24 và thay thế địa chỉ nguồn bởi địa chỉ 24.5.0.5.
Mặc dù quy tắc trên là một quy tắc hợp lệ nhưng mẫu quy tắc này không được khuyến khích dùng mà thay vì chỉ rõ địa chỉ IP người ta thường dùng trên giao tiếp mạng. Chẳng hạn tl0 là giao tiếp mạng bên trong và dc0 là giao tiếp mạng bên ngoài, hãy khai báo các macro ở đầu tệp pf.conf, khi đó quy tắc trên có thể viết thành:
Code:
nat on tl0 from dc0:network to any -> tl0


Việc dùng tên giao tiếp mạng trong các quy tắc NAT có lợi ở chỗ đĩa chỉ IP sẽ được xác định bởi thông tin có trong tệp pf.conf khi nạp PF. Tuy nhiên, nếu sử dụng DHCP để phân phối địa chỉ IP có thể sẽ gặp vấn đề với NAT. Chẳng hạn một giao tiếp mạng đã được cấp một IP mới nhưng NAT vẫn sử dụng IP cũ và vì thế kết nối ra ngoài có thể không thực hiện được. Để khắc phục điều này cần thiết lập cho NAT tự động cập nhật thông tin IP bằng cách sử dụng cặp dấu ngoặc đơn bao tên giao tiếp mạng trong quy tắc NAT:
Code:
nat on tl0 from dc0:network to any -> (tl0)


Phương pháp này có hiệu lực với cả IPv4 và IPv6.

Code:
1.6.6 Ánh xạ chuyển hướng (ánh xạ 1:1)


Ánh xạ chuyển hướng có thể được kiến tạo bằng cách sử dụng quy tắc binat. Quy tắc binat là một quy tắc thực hiện việc ánh xạ một-một giữa một địa chỉ IP bên trong và một địa chỉ IP bên ngoài. Cách này hữu ích trong một số trường hợp. Lấy ví dụ, khi muốn truy cập từ internet vào một máy chủ web ở mạng bên trong cần có sự chuyển đổi từ địa chỉ bên ngoài thành địa chỉ bên trong đối với các gói tin đi vào và ngược lại. Với kiểu NAT này, các cổng TCP và UDP sẽ không bị sửa đổi. Sau đây là một ví dụ về quy tắc bitnat:

web_serv_int = "192.168.1.100"
web_serv_ext = "24.5.0.6"
binat on tl0 from $web_serv_int to any -> $web_serv_ext

1.6.7 Điểm ngoại lệ trong quy tắc NAT
Các ngoại lệ có thể được tạo ra với quy tắc NAT bằng cách sử dụng từ khóa no. Lấy ví dụ, nếu quy tắc NAT ở phần trên được sửa đổi thành:

no nat on tl0 from 192.168.1.208 to any
nat on tl0 from 192.168.1.0/24 to any -> 24.2.74.79

Thì toàn bộ lớp mạng 192.168.1.0/24 sẽ được chuyển đổi thành địa chỉ 24.2.74.79 ngoại trừ 192.168.1.208.
Chú ý: Với quy tắc trên đã xẩy ra trường hợp ngoại lệ là quy tắc thỏa mãn đầu tiên quyết định hành động được áp dụng. Lý do là khi có tự khóa no thì hành động của quy tắc chứa từ khóa này sẽ được áp dụng ngay lập tức. Điều này không đúng với các trường hợp chung của quy tắc trong PF. Từ khóa no cũng có thể được sử dụng trong các quy tắc binat và rdr.

1.6.8 Kiểm tra trạng thái NAT

Để xem tất cả các mục NAT đang hoạt động có thể sử dụng tiện ích pfctl với tham số -s.
Code:
# pfctl -s state
fxp0 TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 
TIME_WAIT:TIME_WAIT
   fxp0 UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53   
MULTIPLE:SINGLE


Sau đây là ý nghĩa của dòng đầu tiên:

- fxp0: Chỉ ra giao tiếp mạng mà trạng thái này liên kết đến, sẽ xuất hiện từ selt nếu trạng thái này ở dạng floating.
- TCP: Giao thức được sử dụng bởi kết nối.
- 192.168.1.35:2132: Địa chỉ IP của giao tiếp mạng bên trong cùng với cổng nguồn, địa chỉ và cổng này sau đó sẽ được thay thế.
- 24.5.0.5:53136: Địa chỉ và cổng của giao tiếp mạng bên ngoài, hai giá trị này sẽ được dùng để thay thế cho hai giá trị địa chỉ và cổng ban đầu của gói tin.
- 65.42.33.245:22: Địa chỉ và cổng đích của gói tin.
- TIME_WAIT:TIME_WAIT: Chỉ ra rằng PF đã tin tưởng vào kết nối TCP này.
[Up] [Print Copy]
  [Article]   PF (Packet Filter) trên OpenBSD 31/01/2010 19:32:02 (+0700) | #4 | 204295
[Avatar]
tmd
Member

[Minus]    0    [Plus]
Joined: 28/06/2006 03:39:48
Messages: 2951
Offline
[Profile] [PM]
Nó là cái bài này nè, dịch từ Anh ngữ sang Việt ngữ.
http://www.openbsd.org/faq/pf/
PF: The OpenBSD Packet Filter
3 giai đoạn của con... người, ban đầu dek biết gì thì phải thăm dò, sau đó biết rồi thì phải thân thiết, sau cùng khi quá thân thiết rồi thì phải tình thương mến thương. Nhưng mà không thương được thì ...
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 Users currently in here 
1 Anonymous

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|