Tôi cần cho phép người dùng (khác với root) chạy máy chủ nghe trên cổng 80.
Có cách nào để làm điều này?
Tôi cần cho phép người dùng (khác với root) chạy máy chủ nghe trên cổng 80.
Có cách nào để làm điều này?
Câu trả lời:
setcap 'cap_net_bind_service=+ep' /path/to/program
điều này sẽ làm việc cho các quy trình cụ thể. Nhưng để cho phép một người dùng cụ thể liên kết với các cổng dưới 1024, bạn sẽ phải thêm anh ta vào sudoers.
Có một cái nhìn vào cuộc thảo luận này để biết thêm.
(Một số phương pháp này đã được đề cập trong các câu trả lời khác; Tôi đang đưa ra một số lựa chọn có thể theo thứ tự ưu tiên.)
Bạn có thể chuyển hướng cổng thấp sang cổng cao và lắng nghe trên cổng cao.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080
Bạn có thể khởi động máy chủ của mình dưới dạng root và bỏ các đặc quyền sau khi nó bắt đầu nghe trên cổng đặc quyền. Tốt hơn là, thay vì tự mã hóa, hãy khởi động máy chủ của bạn từ một trình bao bọc thực hiện công việc cho bạn. Nếu máy chủ của bạn bắt đầu một phiên bản cho mỗi kết nối, hãy khởi động nó từ inetd
(hoặc một chương trình tương tự như xinetd
). Đối với inetd
, sử dụng một dòng như thế này trong /etc/inetd.conf
:
http stream tcp nowait username:groupname /path/to/server/executable argv[0] argv[1]…
Nếu máy chủ của bạn lắng nghe trong một trường hợp duy nhất, hãy khởi động nó từ một chương trình như authbind
. Tạo một tệp trống /etc/authbind/byport/80
và làm cho nó có thể thực thi được đối với người dùng đang chạy máy chủ; hoặc tạo /etc/authbind/byuid/1234
, trong đó 1234 là UID chạy máy chủ, chứa dòng 0.0.0.0/0:80,80
.
Nếu máy chủ thực thi của bạn được lưu trữ trên một hệ thống tệp hỗ trợ các khả năng, bạn có thể cung cấp cho nó khả năng đó . Coi chừng các khả năng vẫn còn tương đối mới và vẫn còn một vài kink .cap_net_bind_service
setcap cap_net_bind_service=ep /path/to/server/executable
-A INPUT -p tcp --dport 1080 -j ACCEPT
nếu không nó sẽ không hoạt động (tôi cũng có một cái -j DROP
bắt tất cả.) Vì vậy, tôi còn lại hai ổ cắm nghe.
Câu trả lời ngắn gọn là điều này là không thể bởi thiết kế.
Câu trả lời dài là trong thế giới nguồn mở có rất nhiều người chơi với thiết kế và đưa ra các phương pháp thay thế. Nói chung, thực tế được chấp nhận rộng rãi rằng điều này là không thể. Thực tế là bạn đang cố gắng có nghĩa là bạn có một lỗi thiết kế khác trong hệ thống của mình và nên xem xét lại toàn bộ kiến trúc hệ thống của bạn theo các thực tiễn tốt nhất và ý nghĩa bảo mật.
Điều đó nói rằng, một chương trình cho phép truy cập không root vào các cổng thấp là authbind . Cả selinux và grsecurance cũng cung cấp khung cho các xác thực được điều chỉnh tốt như vậy.
Cuối cùng, nếu bạn muốn người dùng cụ thể chạy các chương trình cụ thể dưới quyền root và điều bạn thực sự cần chỉ là cho phép người dùng khởi động lại apache hoặc một cái gì đó tương tự, sudo
là bạn của bạn!
Bạn có thể sử dụng chuyển tiếp cổng netcat hoặc xinetd hoặc iptables hoặc sử dụng apache làm proxy mặt trước và chạy quy trình trên một cổng không có đặc quyền.
Authbind , @Gilles đã đề cập đến nó, nhưng tôi muốn mở rộng về nó một chút.
Nó có kiểm soát truy cập thuận tiện (chi tiết trong trang man): bạn có thể lọc truy cập theo cổng, địa chỉ giao diện, uid, phạm vi địa chỉ hoặc cổng và kết hợp cả hai.
Nó có tham số rất hữu ích --depth
:
- cấp độ
Nguyên nhân xác thực ảnh hưởng đến các chương trình nằm ở mức sâu trong biểu đồ cuộc gọi. Mặc định là 1.
"Mức sâu" có nghĩa là khi một tập lệnh (hoặc chương trình), chạy một tập lệnh khác, nó hạ xuống một cấp. Vì vậy, nếu bạn có --depth 5
nghĩa là ở cấp 1 (hoặc là 0?) Đến 5 thì bạn có quyền ràng buộc, trong khi ở cấp 6 trở đi, bạn không được. Hữu ích khi bạn muốn một tập lệnh có quyền truy cập, nhưng không phải là chương trình mà nó chạy có hoặc không có kiến thức của bạn.
Để minh họa, bạn có thể có một cái gì đó như thế này: vì mục đích bảo mật, bạn có một người dùng java
chỉ chạy java và bạn muốn cấp cho anh ta quyền truy cập vào cổng 80:
echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80
Tôi đã tạo ../byport/80 file
, đưa nó cho java
nhóm người dùng (mỗi người dùng có nhóm riêng) và làm cho nó có thể được thực thi theo nhóm, có nghĩa là nó có thể được thực thi bởi java
người dùng. Nếu bạn đang cấp quyền truy cập bằng cổng, thì tệp phải được người dùng thực thi quyền truy cập, vì vậy chúng tôi đã làm điều đó.
Điều này có thể đủ cho Joe trung bình, nhưng vì bạn biết cách sử dụng --depth
tham số, bạn chạy (với tư cách là java
người dùng) authbind --depth [depth] my_web_app's_start_script
bắt đầu --depth 1
và làm việc theo cách của mình cho đến khi bạn tìm thấy độ sâu nhỏ nhất hoạt động và sử dụng nó.
Tôi đã thử phương pháp iptables PREROUTING REDIRECT, nhưng thấy rằng nó cũng ảnh hưởng đến các gói chuyển tiếp. Nghĩa là, nếu máy cũng chuyển tiếp các gói giữa các giao diện (ví dụ: nếu nó hoạt động như một điểm truy cập Wi-Fi được kết nối với mạng Ethernet), thì quy tắc iptables cũng sẽ bắt các kết nối của máy khách được kết nối với các điểm đến Internet và chuyển hướng chúng đến máy. Đó không phải là điều tôi muốn, tôi chỉ muốn chuyển hướng các kết nối được hướng đến chính máy.
Một khả năng là sử dụng chuyển tiếp cổng TCP. Ví dụ: sử dụng socat
:
socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080
Tuy nhiên, một nhược điểm của phương pháp đó là, ứng dụng đang nghe trên cổng 8080 sau đó không biết địa chỉ nguồn của các kết nối đến (ví dụ để ghi nhật ký hoặc các mục đích nhận dạng khác).