열린 PostgreSQL 포트를 보호하는 방법


29

이것이 바로 상황입니다. 고객이 PostgreSQL 데이터베이스에 액세스 할 수있는 개방형 TCP 포트 5432가 필요합니다.

명백한 이유로, 우리는 단지 최후의 수단으로 만 "아니오"라고 말할 수 없습니다.

가장 큰 문제는 무엇입니까? 인프라를 어떻게 방어 할 수 있습니까?

어쨌든 : 왜 세상에 열리지 않아야 합니까? 아마도 20 년 전의 유지 관리되지 않은 FTP 서버보다 더 안전하다고 생각합니다.

PS VPN이 좋지 않습니다. 일부 암호화 는 가능합니다 ( 작동 하는 JDBC 연결 URL을 제공 할 수 있다면 ).


4
SSH 터널은 옵션이 아닌가? 이 하우투 기사에서는 실제로 PostgreSQL 을 예로 사용 합니다 . 고객에게 쉽게 구성 할 수 있도록 사전 구성된 SSH 클라이언트를 제공 할 수 있습니다.
Lucifer Sam

@LuciferSam 아니요. db는 약 100 개의 회사 컴퓨터에서 자체 개발 한 Java 응용 프로그램에서 사용됩니다. 우리를 구성하는 유일한 방법은 로컬 넷 관리에 jdbc 연결 URL을 제공하는 것입니다.

@ milkman 앱은 무엇을합니까? 아마도 RESTful 서버를 대신 쿼리 할 수 ​​있습니까? 분명히, SQL을 REST로
전달해도 아무런

@ tedder42 우리가 호스팅하는 사용자 CMS의 데이터베이스를 조작합니다. 소스를 변경할 권한이 없습니다.

답변:


41

SSL이 필요하고 SELinux를 켜 놓은 상태로 유지하고 로그를 모니터링 하며 현재 PostgreSQL 버전을 사용하십시오 .

서버 측

SSL 필요

에서 postgresql.conf설정 ssl=on하고 (워드 프로세서와의 주석을 참조하여 키 파일 및 certfile가 적절하게 설치되어 있는지 확인하십시오 postgresql.conf).

클라이언트에 대한 특별한 설정없이 클라이언트가 인증서를 신뢰하게하려면 CA에서 인증서를 구입해야 할 수 있습니다.

에서 pg_hba.conf와 같은 사용 무언가 :

hostssl theuser thedatabase 1.2.3.4/32 md5

... 아마도 사용자 및 / 또는 데이터베이스에 대해 "all"을 사용하고 더 넓은 소스 IP 주소 필터를 사용합니다.

로그인 할 수있는 사용자 제한, 원격 수퍼 유저 로그인 거부

가능하면 사용자에게 "모두"를 허용하지 마십시오. 필요하지 않은 경우 수퍼 유저 로그인을 원격으로 허용하지 않습니다.

사용자의 권리 제한

로그인 할 수있는 사용자의 권한을 제한하십시오. 사용자 CREATEDB또는 CREATEUSER권한을 부여하지 마십시오 .

REVOKECONNECT에서 바로 PUBLIC모든 데이터베이스에 후 데이터베이스에 대한 액세스 할 수 있어야합니다 사용자 만 / 역할에 다시 제공합니다. (사용자를 역할로 그룹화하고 개별 사용자가 아닌 역할에 대한 권한을 부여하십시오).

원격 액세스 권한이있는 사용자는 필요한 DB에만 연결할 수 있고 실제로 필요한 스키마, 테이블 및 열에 대한 권한 만 보유해야합니다. 이것은 로컬 사용자에게도 좋은 방법입니다. 합리적인 보안입니다.

클라이언트 설정

PgJDBC에서 매개 변수를 전달하십시오ssl=true .

JDBC 드라이버가 SSL 연결을 시도하고 설정하도록 지시하려면 연결 URL 매개 변수 ssl = true를 추가해야합니다.

... 및 클라이언트의 신뢰 저장소에 서버 인증서를 설치하거나 사용자가 인증서를 설치하지 못하게하려면 Java의 내장 신뢰 저장소에있는 CA 중 하나가 신뢰하는 서버 인증서를 사용하십시오.

지속적인 행동

이제 PostgreSQL을 최신 상태로 유지하십시오 . PostgreSQL에는 몇 가지 사전 인증 보안 허점 만 있었지만 0보다 크므로 최신 상태로 유지하십시오. 어쨌든 버그 수정은 좋은 것입니다.

액세스 할 필요가없는 대규모 넷 블록 / 지역이있는 경우 방화벽을 앞에 추가하십시오.

연결 및 연결 끊기 (참조 postgresql.conf). 실용적인 경우 쿼리를 기록합니다. 가능한 경우 침입 감지 시스템 또는 fail2ban 또는 이와 유사한 장치를 앞에서 실행하십시오. postgres가있는 fail2ban의 경우 편리한 사용법이 있습니다.

로그 파일을 모니터하십시오.

보너스 편집증

고려해야 할 추가 단계 ...

클라이언트 인증서 필요

원하는 경우 pg_hba.conf클라이언트가 서버에서 신뢰하는 X.509 클라이언트 인증서를 제시하도록 요구할 수도 있습니다 . 서버 인증서와 동일한 CA를 사용할 필요가 없습니다. homebrew openssl CA를 사용하여이를 수행 할 수 있습니다. JDBC 사용자는 클라이언트 인증서를 Java Keystore로 가져 와서 keytool일부 JSSE 시스템 특성을 구성하여 Java를 해당 키 저장소로 지정해야합니다. 따라서 완전히 투명하지는 않습니다.

인스턴스 검역

실제로 편집증 환자가 되려면 별도의 컨테이너 / VM에서 또는 적어도 다른 사용자 계정으로 필요한 데이터베이스만으로 클라이언트 인스턴스를 실행하십시오.

그렇게하면 PostgreSQL 인스턴스가 손상되면 더 이상 얻을 수 없습니다.

SELinux 사용

나는 이것을 말할 필요는 없지만 ...

RHEL 6 또는 7과 같은 SELinux 지원 시스템을 실행하고 SELinux를 끄거나 허용 모드로 설정하지 마십시오 . 강제 모드로 유지하십시오.

기본이 아닌 포트 사용

에 의해 보안 에만 무명은 어리 석음이다. 현명한 일을 한 후에는 약간의 모호함을 사용하는 보안이 손상되지 않을 것입니다.

기본이 아닌 포트에서 Pg를 실행하면 자동화 된 공격자의 삶이 조금 더 어려워집니다.

프록시를 앞에 두십시오

연결 풀 및 프록시 역할을하는 PostgreSQL 앞에서 PgBouncer 또는 PgPool-II를 실행할 수도 있습니다. 그렇게하면 프록시가 실제 데이터베이스 호스트가 아닌 SSL을 처리하도록 할 수 있습니다. 프록시는 별도의 VM 또는 컴퓨터에있을 수 있습니다.

클라이언트 응용 프로그램에 이미 기본 제공 풀이없는 경우 연결 풀링 프록시를 사용하는 것이 일반적으로 PostgreSQL에서 좋은 생각입니다. 대부분의 Java 응용 프로그램 서버, Rails 등에는 기본 제공 풀링이 있습니다. 그럼에도 서버 측 풀링 프록시는 최악의 상태입니다.


3
클라이언트에 정적 $ IP가있는 경우 방화벽을 통해서도 $ port까지 허용하십시오.
user9517은 GoFundMonica

대단히 감사합니다! Pgjdbc에는이 매개 변수가 있지만 jdbc 연결 URL 만 제공 할 수 있으며 Java 응용 프로그램 (독점적이며 논쟁의 여지가없는)과 작동하는지 확실하지 않습니다. 좋아, 그렇지 않으면 나는 새로운 질문을 할 것이다. 자세한 답변 감사합니다!

1
@lesto 사실, VPN을 노출하면 하나의 제한된 서비스에 비해 공격 영역이 크게 증가 한다고 생각 합니다. 사람들은 VPN이 원격 시스템의 모든 맬웨어가 공격 경계 채널이되어 모든 경계 보안을 뚫고 네트워크의 장에 도달한다는 것을 잊습니다. 인터넷 호스트처럼 유독 한 것으로 취급하는 DMZ에 연결하는 경우에만 허용됩니다.
Craig Ringer

1
@CraigRinger 나는 보호의 나머지 부분을 제거하는 것이 아니라 VPN으로 서비스를 캡슐화한다고 말하고 있습니다
Lesto

1
@lesto 물론, 많은 관리자들이 불행히도 VPN을 Magic Security Sauce로 취급하지 않는다면 VPN은 유용한 추가 계층이 될 수 있습니다.
Craig Ringer

2

Craigs 인상적인 행동 계획의 간단한 확장 :

어쩌면 사용자는 상대적으로 작은 네트워크 공급자 세트만을 사용하고있을 것입니다 (예 : 이동 중 그의 모빌 네트워크 공급자, 집에서 케이블 네트워크, 직장에서 나가는 직장 IP).

대부분의 네트워크 공급자에는 많은 IP가 있지만 실제로는 많은 서브넷이 없습니다. 따라서 iptables 필터를 제공하면 postgresql이 고객이 사용하는 네트워크 세그먼트에 대한 액세스를 제한 할 수 있습니다. 이것은 무작위로 선택된 네트의 문제 소스의 공격 가능성을 크게 줄였습니다.

간단한 지원 시나리오 :

  1. 고객이 "로그인 할 수 없습니다"라고 전화합니다 .
  2. tcpdump -i eth0 -p tcp port 5432어디에서 왔는지 명령으로 알아낼 수 있습니다.
  3. 를 사용하면 whois 1.2.3.4이 IP가 사용하는 IP 주소를 얻을 수 있습니다. 예를 들어, 일 수 있습니다 1.2.3.0/24.
  4. 으로 iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT(또는 유사) 당신은 그의 새로운 서브넷와 TCP 연결을 할 수 있습니다.

uif영구적이고 직관적 인 선언 가능한 iptables 규칙 세트를 제공 할 수 있는 매우 우수한 perl 스크립트 가 있습니다. "uif iptables"용 Google.


1
재미있는 생각이지만, 그것은 약간 깨지기 쉬운 것 같습니다.
nishantjr

@nishantjr 물론 이것은 독립형 솔루션이 아니며 상황을 개선 할 수있는 가능성 일뿐입니다.
peterh는 모니카

보다 실질적인 접근 방법은 개별 ISP 및 / 또는 국가를 허용 목록에 추가하는 것입니다. 예를 들어 stackoverflow.com/questions/16617607/…
Josip Rodin

1

위의 링크 된 HOWTO를 기반으로 PostgreSQL을위한 상당히 간단한 Fail2ban 구성이 있지만 실제로 우분투 패키지로 작업하고 다른 오류 조건을 포착하고 다양한 디버그 메시지를 건너 뛰어 더 빠르게 만들 수 있도록 미세 조정되었습니다.

/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은 강력한 도구이지만 필터가 그대로 작동한다는 것을 믿지 마십시오. failregex 도구를 사용하여 필터를 테스트하고 따옴표를 이스케이프해야합니다 (예 : "admin"은 \ "admin \"임). 예를 들어, 내 /etc/log/postgresql/postgresql-9.3-main.log에서 다음 필터 failregex 줄을 테스트해도 효과가 없었습니다.

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

위는 나에게 주었다

실패 정규식 : 0 총계

로그 형식과 일치하도록 failregex를 업데이트해야했습니다.

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

이것은 나에게 긍정적 인 결과를 주었다.

Failregex : 총 1 개

fail2ban-regex 테스트는 전체 로그 파일에서 구현 될 수도 있습니다.

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

위의 내용은 업데이트 된 failregex로 다음과 같은 긍정적 인 결과를 냈습니다.

실패 정규식 : 총 169 개

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.