Làm thế nào để bảo mật một cổng PostgreSQL đang mở


29

Vì vậy, đây là tình huống. Có vẻ như chúng ta cần phải có một cổng TCP mở 5432 ra thế giới, nơi một khách hàng có quyền truy cập vào cơ sở dữ liệu PostgreQuery của mình.

Vì những lý do rõ ràng, chúng ta không thể nói chỉ "không", chỉ là phương sách cuối cùng.

Những rắc rối lớn nhất là gì? Làm thế nào tôi có thể bảo vệ cơ sở hạ tầng của chúng tôi?

Dù sao: tại sao nó không nên được mở ra cho thế giới? Tôi nghĩ rằng, có lẽ nó an toàn hơn một số máy chủ FTP 20 năm tuổi, không rõ ràng.

PS VPN không ổn. Một số mã hóa có thể (nếu tôi có thể cung cấp cho anh ấy URL kết nối JDBC hoạt động ).


4
Đường hầm SSH không phải là một lựa chọn? Bài viết hướng dẫn này thực sự sử dụng PostgreSQL làm ví dụ. Bạn có thể cung cấp cho khách hàng một máy khách SSH được cấu hình sẵn để dễ dàng kết nối.
Lucifer Sam

@LuciferSam Không. Db sẽ được sử dụng bởi một ứng dụng java được phát triển nội bộ trên khoảng 100 máy của công ty. Cách duy nhất của chúng tôi để định cấu hình chúng là cung cấp url kết nối jdbc cho quản trị localnet của chúng, bất kỳ cái nào khác đều rất có vấn đề.

@milkman ứng dụng này làm gì? có lẽ nó có thể truy vấn một máy chủ RESTful thay thế? Rõ ràng, việc chuyển SQL sang REST không thu được gì, nhưng giả sử đó là CRUD ..
tedder42

@ tedder42 Nó thao túng cơ sở dữ liệu của người dùng CMS, được lưu trữ bởi chúng tôi. Chúng tôi không được phép thay đổi nguồn của nó.

Câu trả lời:


41

Yêu cầu SSL, bật Selinux, theo dõi nhật ký và sử dụng phiên bản PostgreQuery hiện tại .

Phía máy chủ

Yêu cầu SSL

Trong postgresql.conftập hợp ssl=onvà đảm bảo rằng bạn đã cài đặt keyfile và certfile một cách thích hợp (xem tài liệu và các bình luận trong postgresql.conf).

Bạn có thể cần mua chứng chỉ từ CA nếu bạn muốn khách hàng tin tưởng mà không cần thiết lập đặc biệt cho khách hàng.

Trong pg_hba.confsử dụng một cái gì đó như:

hostssl theuser thedatabase 1.2.3.4/32 md5

... có thể với "tất cả" cho người dùng và / hoặc cơ sở dữ liệu và có thể với bộ lọc địa chỉ IP nguồn rộng hơn.

Giới hạn người dùng có thể đăng nhập, từ chối đăng nhập siêu người dùng từ xa

Đừng cho phép "tất cả" cho người dùng nếu có thể; bạn không muốn cho phép đăng nhập siêu người dùng từ xa nếu bạn có thể tránh được nhu cầu đó.

Giới hạn quyền của người dùng

Hạn chế quyền của người dùng có thể đăng nhập. Đừng cung cấp cho họ CREATEDBhoặc CREATEUSERquyền.

REVOKEcác CONNECTngay từ PUBLICtrên tất cả các cơ sở dữ liệu của bạn, sau đó trả lại cho những người dùng / vai trò đó sẽ có thể truy cập cơ sở dữ liệu đó. (Nhóm người dùng thành vai trò và cấp quyền cho vai trò, thay vì trực tiếp cho người dùng cá nhân).

Đảm bảo rằng người dùng có quyền truy cập từ xa chỉ có thể kết nối với DB họ cần và chỉ có quyền đối với các lược đồ, bảng và cột trong phạm vi mà họ thực sự cần. Đây cũng là một cách làm tốt cho người dùng địa phương, đó chỉ là bảo mật hợp lý.

Thiết lập máy khách

Trong PGJDBC, truyền tham sốssl=true :

Để hướng dẫn trình điều khiển JDBC thử và thiết lập kết nối SSL, bạn phải thêm tham số URL kết nối ssl = true.

... và cài đặt chứng chỉ máy chủ trong kho tin cậy của máy khách hoặc sử dụng chứng chỉ máy chủ được một trong các CA tin cậy trong kho tin cậy tích hợp của Java nếu bạn không muốn người dùng phải cài đặt chứng chỉ.

Hành động liên tục

Bây giờ hãy chắc chắn rằng bạn luôn cập nhật PostgreSQL . PostgreSQL chỉ có một vài lỗ hổng bảo mật trước khi xác thực, nhưng đó là nhiều hơn không, vì vậy hãy cập nhật. Dù sao thì bạn cũng nên sửa lỗi.

Thêm tường lửa ở phía trước nếu có các netblocks / vùng lớn mà bạn biết bạn không cần truy cập từ đó.

Đăng nhập kết nối và ngắt kết nối (xem postgresql.conf). Đăng nhập truy vấn nếu thực tế. Chạy một hệ thống phát hiện xâm nhập hoặc fail2ban hoặc tương tự ở phía trước nếu thực tế. Đối với fail2ban với postgres, có một cách thuận tiện tại đây

Giám sát các tệp nhật ký.

Tiền thưởng hoang tưởng

Thêm các bước để suy nghĩ về ...

Yêu cầu chứng chỉ ứng dụng khách

Nếu bạn muốn, bạn cũng có thể sử dụng pg_hba.confđể yêu cầu khách hàng xuất trình chứng chỉ ứng dụng khách X.509 được máy chủ tin cậy. Không cần sử dụng cùng một CA với chứng chỉ máy chủ, bạn có thể thực hiện việc này với CA openslrew homebrew. Người dùng JDBC cần nhập chứng chỉ ứng dụng khách vào Kho khóa Java của họ keytoolvà có thể định cấu hình một số thuộc tính hệ thống JSSE để trỏ Java vào kho khóa của họ, vì vậy nó không hoàn toàn trong suốt.

Kiểm dịch ví dụ

Nếu bạn muốn thực sự hoang tưởng, hãy chạy ví dụ cho máy khách trong một thùng chứa / VM riêng hoặc ít nhất là dưới một tài khoản người dùng khác, chỉ với (các) cơ sở dữ liệu mà họ yêu cầu.

Theo cách đó, nếu họ thỏa hiệp với cá thể PostgreQuery, họ sẽ không nhận được thêm nữa.

Sử dụng SELinux

Tôi không cần phải nói điều này, nhưng ...

Chạy một máy có hỗ trợ SELinux như RHEL 6 hoặc 7 và không tắt Selinux hoặc đặt ở chế độ cho phép . Giữ nó trong chế độ thực thi.

Sử dụng cổng không mặc định

Bảo mật chỉ bởi sự tối nghĩa là sự ngu ngốc. Bảo mật sử dụng một chút tối nghĩa một khi bạn đã thực hiện các công cụ hợp lý có thể sẽ không bị tổn thương.

Chạy PG trên một cổng không mặc định để làm cho cuộc sống khó khăn hơn đối với những kẻ tấn công tự động.

Đặt một proxy ở phía trước

Bạn cũng có thể chạy PGBouncer hoặc PGPool-II trước PostgreSQL, hoạt động như một nhóm kết nối và proxy. Bằng cách đó, bạn có thể để proxy xử lý SSL, không phải máy chủ cơ sở dữ liệu thực. Proxy có thể nằm trên một máy ảo hoặc máy riêng biệt.

Dù sao, việc sử dụng proxy tổng hợp kết nối thường là một ý tưởng hay với PostgreSQL, trừ khi ứng dụng khách đã có sẵn một nhóm tích hợp. Hầu hết các máy chủ ứng dụng Java, Rails, v.v. đều được tích hợp sẵn. Ngay cả sau đó, một proxy tổng hợp phía máy chủ là vô hại nhất.


3
Nếu máy khách có $ IP tĩnh, chỉ cho phép thông qua tường lửa thành $ port.
user9517 hỗ trợ GoFundMonica

Cảm ơn nhiều! PGjdbc có thông số này, nhưng tôi chỉ có thể cung cấp cho anh ta một url kết nối jdbc và tôi không chắc liệu nó có hoạt động với ứng dụng java của mình không (độc quyền, không thể truy cập được). Ok, nếu không tôi sẽ hỏi một câu hỏi mới. Cảm ơn bạn câu trả lời chi tiết của bạn!

1
@lesto Trên thực tế, tôi nghĩ việc phơi bày VPN ồ ạt làm tăng bề mặt tấn công so với chỉ một dịch vụ bị hạn chế. Mọi người quên rằng VPN sau đó trở thành một kênh tấn công cho bất kỳ phần mềm độc hại nào trên (các) máy từ xa để vượt qua tất cả các bảo mật vành đai và đi vào ruột của mạng. Tôi chỉ thấy chúng có thể chấp nhận được nếu chúng kết nối với DMZ coi chúng cũng độc hại như máy chủ Internet.
Craig Ringer

1
@CraigRinger Tôi không nói sẽ loại bỏ phần còn lại của bảo vệ, mà là đóng gói dịch vụ vào VPN
Lesto

1
@lesto Chắc chắn, đã đồng ý, VPN có thể là một lớp bổ sung hữu ích nếu nó không được coi là Magic Security Sauce như nhiều quản trị viên không may làm.
Craig Ringer

2

Một phần mở rộng đơn giản cho kế hoạch hành động ấn tượng của Craigs:

Có thể người dùng chỉ sử dụng một nhóm nhỏ các nhà cung cấp mạng tương đối (ví dụ: nhà cung cấp mạng huy động của anh ta trong khi di chuyển, mạng cáp của anh ta từ nhà và nơi làm việc ip đi làm từ công sở).

Hầu hết các nhà cung cấp mạng có nhiều IP, nhưng không thực sự có nhiều mạng con. Vì vậy, bạn có thể cung cấp bộ lọc iptables, giới hạn quyền truy cập postgresql vào các phân đoạn mạng được sử dụng bởi khách hàng của bạn. Điều này làm giảm đáng kể khả năng tấn công của các nguồn rắc rối được lựa chọn ngẫu nhiên của mạng.

Một kịch bản hỗ trợ đơn giản:

  1. Khách hàng của bạn gọi cho bạn, "Tôi không thể đăng nhập" .
  2. Bạn tìm ra với một tcpdump -i eth0 -p tcp port 5432lệnh, anh ta đến từ đâu.
  3. Với một whois 1.2.3.4bạn có thể lấy địa chỉ IP được sử dụng bởi ip này. Ví dụ, nó có thể 1.2.3.0/24.
  4. Với một iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT(hoặc một số tương tự), bạn cho phép các kết nối tcp với mạng con mới của mình.

Có một kịch bản perl rất tốt có tên uifcó thể cung cấp các quy tắc iptables có thể khai báo vĩnh viễn và trực quan. (Google cho "uif iptables").


1
Ý tưởng thú vị, nhưng điều đó nghe có vẻ hơi mong manh.
nishantjr

@ Vecantjr Tất nhiên nó không phải là một giải pháp độc lập, chỉ có khả năng làm cho mọi thứ tốt hơn.
peterh nói rằng phục hồi Monica

Một cách tiếp cận thực tế hơn có thể là đưa vào danh sách trắng các ISP và / hoặc quốc gia riêng lẻ, để biết cách thực hiện việc này, ví dụ: stackoverflow.com/questions/16617607/ Kẻ
Josip Rodin

1

Đây là một cấu hình Fail2ban khá đơn giản cho PostgreSQL dựa trên HOWTO được liên kết ở trên nhưng được tinh chỉnh để thực sự hoạt động với các gói Ubuntu, nắm bắt một điều kiện lỗi khác và bỏ qua các thông báo gỡ lỗi khác nhau để làm cho nó nhanh hơn:

/etc/fail2ban/filter.d/local-postgresql.conf:

[Definition]

failregex = <HOST>\(\d+\) FATAL:  password authentication failed for .+$
            <HOST>\(\d+\) FATAL:  no pg_hba.conf entry for host .+$

ignoreregex = duration:

/etc/fail2ban/jail.d/local-postgresql.conf:

[local-postgresql]
enabled  = true
filter   = local-postgresql
action   = iptables[name=PostgreSQL, port=5432, protocol=tcp]
           sendmail-whois[name=PostgreSQL, dest=root@localhost]
logpath  = /var/log/postgresql/postgresql-9.3-main.log
maxretry = 3

1

Fail2ban là một công cụ mạnh mẽ, nhưng đừng tin rằng bộ lọc sẽ hoạt động như bình thường. Kiểm tra mọi bộ lọc bằng công cụ failregex và nhớ thoát bất kỳ dấu ngoặc kép nào (Tức là "quản trị viên" sẽ là \ "admin \"). Ví dụ: kiểm tra dòng failregex của bộ lọc sau từ /etc/log/postgresql/postgresql-9.3-main.log không hoạt động với tôi.

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' '<HOST>\(\d+\) FATAL:  password authentication failed for .+$'

Ở trên đã cho tôi

Failregex: 0 tổng

Tôi đã phải cập nhật failregex để phù hợp với định dạng nhật ký.

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' 'FATAL:  password authentication failed for user \"<HOST>\"'

Điều này đã cho tôi một kết quả tích cực.

Failregex: tổng cộng 1

Kiểm tra fail2ban-regex cũng có thể được thực hiện trên toàn bộ tệp nhật ký.

fail2ban-regex /var/log/postgresql/postgresql-9.3-main.log /etc/fail2ban/filter.d/postgresql.local

Ở trên đã cho tôi kết quả tích cực sau đây với failregex được cập nhật.

Failregex: tổng cộng 169

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.