Iptables: khớp lưu lượng đi với conntrack và chủ sở hữu. Hoạt động với những giọt lạ


11

Trong kịch bản iptables của tôi, tôi đã thử nghiệm viết các quy tắc chi tiết nhất có thể. Tôi giới hạn người dùng nào được phép sử dụng dịch vụ nào, một phần để bảo mật và một phần là bài tập học tập.

Sử dụng iptables v1.4.16.2 trên Debian 6.0.6 chạy kernel 3.6.2.

Tuy nhiên tôi đã gặp phải một vấn đề mà tôi chưa hiểu rõ lắm ..

cổng đi cho tất cả người dùng

Điều này hoạt động hoàn toàn tốt. Tôi không có bất kỳ quy tắc theo dõi nhà nước chung chung.

## Cổng đi 81
$ IPTABLES -A OUTPUT -p tcp --dport 81 -m conntrack --ctstate MỚI, THÀNH LẬP -j CHẤP NHẬN
$ IPTABLES -A INPUT -p tcp --sport 81 -s $ MYIP -m conntrack --ctstate ESTABOUNDED -j CHẤP NHẬN

cổng đi với người dùng phù hợp

## cổng đi 80 cho tài khoản người dùng
$ IPTABLES -A OUTPUT --match chủ sở hữu - người dùng chủ sở hữu tài khoản -p tcp --dport 80 -m conntrack --ctstate MỚI, THÀNH LẬP --sport 1024: 65535 -j CHẤP NHẬN
$ IPTABLES -A INPUT -p tcp --sport 80 --dport 1024: 65535 -d $ MYIP -m conntrack --ctstate THÀNH LẬP -j CHẤP NHẬN

Điều này cho phép cổng 80 chỉ dành cho tài khoản "tài khoản người dùng", nhưng các quy tắc như thế này đối với lưu lượng TCP có vấn đề.

## Nhật ký gửi đi mặc định + quy tắc chặn
$ IPTABLES -A OUTPUT -j LOG --log-prefix "BAD OUTGOING" --log-ip-Tùy chọn --log-tcp-Tùy chọn --log-uid
$ IPTABLES -A ĐẦU RA -j DROP

Vấn đề

Các công việc trên, người dùng "tài khoản người dùng" có thể nhận được các tập tin hoàn toàn tốt. Không có người dùng nào khác trên hệ thống có thể thực hiện các kết nối gửi đến cổng 80.

useraccount @ host: $ wget http://cachefly.cachefly.net/10mb.test

Nhưng wget ở trên lá x7 đã bỏ các mục trong syslog của tôi:

Ngày 18 tháng 10 02:00:35 nhân xxxx SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 WINDOW = 979 RES = 0x00 ACK URGP = 0  

Tôi không nhận được những giọt này cho các quy tắc tương tự với lưu lượng UDP. Tôi đã có các quy tắc giới hạn người dùng có thể thực hiện các yêu cầu DNS.

Các gói ACK bị loại bỏ dường như đến từ tài khoản gốc (URGP = 0) mà tôi không hiểu. Ngay cả khi tôi trao đổi useraccount cho root.

Tôi tin rằng các gói ACK được phân loại là mới vì conntrack bắt đầu theo dõi các kết nối sau bước thứ 3 của bắt tay 3 cách, nhưng tại sao lại bị loại bỏ?

Những giọt này có thể được bỏ qua một cách an toàn?

Biên tập

Vì vậy, tôi thường thấy các quy tắc như thế này, hoạt động tốt với tôi:

$ IPTABLES -A OUTPUT -s $ MYIP -p tcp -m tcp --dport 80 -m state --state MỚI, THÀNH LẬP -j CHẤP NHẬN
$ IPTABLES -A INPUT -p tcp -m tcp --sport 80 -d $ MYIP -m state --state ESTABOUNDED -j CHẤP NHẬN

Tôi đã hoán đổi "-m state --state" cho "-m conntrack --ctstate" vì trạng thái khớp rõ ràng là lỗi thời.

Là thực hành tốt nhất để có quy tắc theo dõi nhà nước chung chung? Là các quy tắc trên không được coi là chính xác?

Để kiểm soát chặt chẽ các kết nối người dùng đi sẽ như thế này sẽ tốt hơn?

$ IPTABLES -A INPUT -m conntrack - được thành lập -j CHẤP NHẬN
$ IPTABLES -A OUTPUT -m conntrack --ctstate THÀNH LẬP -j CHẤP NHẬN

$ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate MỚI -m chủ sở hữu - người dùng chủ sở hữu tài khoản -j ACCEPT

$ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate MỚI -m chủ sở hữu - chủ sở hữu otheraccount -j CHẤP NHẬN

Bạn có thể vui lòng đăng tất cả các quy tắc bao gồm chuỗi FORWARD và bảng nat nếu máy chủ này cũng định tuyến lưu lượng truy cập từ LAN.
Serge

Máy chủ này không thực hiện bất kỳ định tuyến nào, lưu lượng truy cập bắt nguồn từ máy với các quy tắc này. Tôi chỉ đăng các quy tắc có liên quan cho lưu lượng đi cụ thể.
arcX

Câu trả lời:


16

Để cắt ngắn một câu chuyện dài, ACK đó đã được gửi khi ổ cắm không thuộc về ai. Thay vì cho phép các gói liên quan đến một ổ cắm thuộc về người dùng x, hãy cho phép các gói liên quan đến một kết nối được khởi tạo bởi một ổ cắm từ người dùng x.

Câu chuyện dài hơn.

Để hiểu vấn đề, nó giúp hiểu cách thức wgetvà các yêu cầu HTTP hoạt động nói chung.

Trong

wget http://cachefly.cachefly.net/10mb.test

wgetthiết lập kết nối TCP tới cachefly.cachefly.netvà sau khi được thiết lập sẽ gửi yêu cầu trong giao thức HTTP có nội dung: "Vui lòng gửi cho tôi nội dung của /10mb.test( GET /10mb.test HTTP/1.1) và nhân tiện, bạn có thể vui lòng không đóng kết nối sau khi bạn hoàn thành ( Connection: Keep-alive). đó là vì trong trường hợp máy chủ trả lời chuyển hướng cho một URL trên cùng một địa chỉ IP, nó có thể sử dụng lại kết nối.

Bây giờ, máy chủ có thể trả lời, "ở đây có dữ liệu bạn yêu cầu, hãy cẩn thận với dung lượng lớn 10 MB ( Content-Length: 10485760) và vâng, tôi sẽ để kết nối mở". Hoặc nếu nó không biết kích thước của dữ liệu, "Đây là dữ liệu, xin lỗi tôi không thể để kết nối mở nhưng tôi sẽ nói khi nào bạn có thể ngừng tải xuống dữ liệu bằng cách đóng kết nối của tôi".

Trong URL ở trên, chúng tôi trong trường hợp đầu tiên.

Vì vậy, ngay sau khi wgetnhận được các tiêu đề cho phản hồi, nó biết công việc của mình được thực hiện khi đã tải xuống 10MB dữ liệu.

Về cơ bản, những gì wgetđược đọc dữ liệu cho đến khi 10MB đã được nhận và thoát. Nhưng tại thời điểm đó, có nhiều việc phải làm. Còn máy chủ thì sao? Nó được yêu cầu để lại kết nối mở.

Trước khi thoát, hãy wgetđóng ( closegọi hệ thống) bộ mô tả tệp cho ổ cắm. Sau đó, closehệ thống hoàn tất xác nhận dữ liệu được gửi bởi máy chủ và gửi FINthông báo: "Tôi sẽ không gửi thêm bất kỳ dữ liệu nào". Tại thời điểm đó closetrở lại và wgetthoát. Không có ổ cắm liên quan đến kết nối TCP nữa (ít nhất không phải là sở hữu của bất kỳ người dùng nào). Tuy nhiên nó vẫn chưa kết thúc. Khi nhận được điều đó FIN, máy chủ HTTP sẽ thấy phần cuối của tệp khi đọc yêu cầu tiếp theo từ máy khách. Trong HTTP, điều đó có nghĩa là "không còn yêu cầu nữa, tôi sẽ kết thúc". Vì vậy, nó cũng gửi FIN của mình, để nói, "Tôi cũng sẽ không gửi bất cứ thứ gì, kết nối đó sẽ biến mất".

Khi nhận được FIN đó, khách hàng sẽ gửi "ACK". Nhưng, tại thời điểm đó, wgetđã qua lâu, do đó ACK không phải từ bất kỳ người dùng nào. Đó là lý do tại sao nó bị chặn bởi tường lửa của bạn. Vì máy chủ không nhận được ACK, nên nó sẽ gửi FIN nhiều lần cho đến khi nó từ bỏ và bạn sẽ thấy nhiều ACK bị rơi hơn. Điều đó cũng có nghĩa là bằng cách loại bỏ các ACK đó, bạn không cần sử dụng tài nguyên của máy chủ (cần duy trì ổ cắm ở trạng thái LAST-ACK) trong một thời gian.

Hành vi sẽ khác nếu khách hàng không yêu cầu "Keep-life" hoặc máy chủ không trả lời "Keep-life".

Như đã đề cập, nếu bạn đang sử dụng trình theo dõi kết nối, điều bạn muốn làm là để mọi gói tin ở trạng thái THÀNH LẬP và LIÊN QUAN thông qua và chỉ lo lắng về các NEWgói.

Nếu bạn cho phép các NEWgói từ người dùng xnhưng không phải các gói từ người dùng y, thì các gói khác cho các kết nối được thiết lập bởi người dùng xsẽ đi qua và vì người dùng không thể thiết lập kết nối y(vì chúng tôi đang chặn các NEWgói sẽ thiết lập kết nối), sẽ không có bất kỳ gói tin nào cho các ykết nối người dùng đi qua.


3

Điều này cho phép cổng 80 chỉ dành cho tài khoản "useraccount"

- tốt, ít nhất là các quy tắc bạn đã thể hiện không ngụ ý điều này, thực sự.

Ngoài ra còn có một phòng để tư vấn - đừng kiểm tra người dùng trên các luồng THÀNH LẬP, chỉ cần thực hiện kiểm tra trên MỚI. Tôi cũng không thấy một điểm nào trong việc kiểm tra cổng nguồn khi kiểm tra Thành lập sắp tới, sự khác biệt của cổng đó là gì, nó đã ở trạng thái THÀNH LẬP từ PoV của conntrack. Tường lửa nên đơn giản nhất có thể nhưng hiệu quả chưa, vì vậy phương pháp dao cạo của Occam là phù hợp nhất.


1
Cảm ơn vì lời khuyên. Thông thường tôi là tất cả vì đơn giản nhưng đó không phải là điểm của bài tập đặc biệt này.
arcX

1
@arcX, bài tập này có thể thất bại do quá phức tạp và không nhất quán - IOW, hành vi bạn thấy có thể không phải do nội bộ của bộ lọc mạng (lỗi, quirks), mà là do cách bạn sử dụng nó. Cố gắng đơn giản hóa bộ quy tắc đầu tiên
poige
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.