기본 HTTP 웹 서버에 대한 안전한 표준 iptables 규칙 세트


15

HTTP (S) 및 SSH (포트 80, 443 및 22)를 사용하여 기본 웹 서버를 실행하는 대부분의 사이트에서 작동하는 기본 서버 iptables 스크립트를 작성하려고했습니다. 결국 대부분의 VPS는 이러한 시작 포트 규칙 만 필요하며 나중에 필요에 따라 메일 또는 게임 포트를 추가 할 수 있습니다.

지금까지 나는 다음과 같은 규칙을 가지고 있으며 누군가 더 나은 스크립트 또는 추가 할 수있는 개선 사항을 알고 있는지 궁금합니다.

*filter

#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allows SSH connections (only 4 attempts by an IP every 3 minutes, drop the rest)
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

iptables는 상자를 보호하는 데 가장 중요한 부분 중 하나이며 (fail2ban 참조) 서버의 안전한 기본 방화벽을 만드는 데 필요한 모든 것을 이해하는 데 어려움을 겪는 사람들이 많이 있습니다.

웹 서버에 필요한 기본 포트만 여는 가장 안전한 방법은 무엇입니까?

업데이트 : cyberciti.biz에는 또 다른 iptables 스크립트 가 있습니다.

또한 Denyhosts 또는 fail2ban을 사용하는 대신 iptables 자체를 사용 하여 SSH에서 반복되는 잘못된 시도를 차단할 수 있습니다 .


당신은 그것이 VPS라고 말합니다. LAN IP도 있다고 가정합니까? 서브넷의 모든 컴퓨터를 신뢰하십니까? 편집증을 어떻게 원하십니까? OUTPUT 필터링을 사용하여 장비를 더욱 안전하게 보호 할 수 있습니다. 알려 주시면 사용 제안한 내용에 응답 할 수 있습니다.
hobodave

좋은 점은 대부분의 VPS가 LAN에서 다른 사람과 액세스 할 수있는 VM에 있다는 점을 감안할 때 신뢰할 수없는 시작이 현명한 출발점이 될 것입니다. 추가 VPS가있는 경우 나중에 규칙에 추가하여 규칙에 액세스 할 수 있습니다 (예 : 웹 서버에서 데이터베이스로).
Xeoncross

1
경고 : 언급되어 있고 modprobe설치되지 않은 cyberciti.biz 스크립트를 실행 하거나 (또는 ​​포트 22를 열기 전에 다른 오류가있는 경우) 서버에서 사용자를 잠급니다.
EoghanM

답변:


14

iptables를 사용하는 가장 안전한 방법은 모든 것을 닫고 필요한 것만 여는 것입니다. 나는 정신이 산만하다. 그래서 나는 항상 가능한 한 게 으르려고 노력한다. 그래서 나는 서버를 불 안전하게 만들 수있는 실수를하지 않는다.

나는 이것을 사용합니다. 작동하기 위해서는 약간의 변수 할당 만 수행해야합니다.

  #!/bin/bash +x

  # first author: marcos de vera
  # second: joan marc riera

  ip=/sbin/iptables
  mriera="xx.xx.xx.xx"
  nsancho="yy.yy.yy.yy"
  admins="$mriera $nsancho "
  sshers=""
  mysqlrs="zz.zz.zz.zz/23"
  snmprs="uu.uu.uu.uu"
  tcpservices="80 443 22"
  udpservices=""

  # Firewall script for servername

  echo -n ">> Applying iptables rules... "

  ## flushing...
  $ip -F
  $ip -X
  $ip -Z
  $ip -t nat -F

  # default: DROP!
  $ip -P INPUT DROP
  $ip -P OUTPUT DROP
  $ip -P FORWARD DROP

  # filtering...

  # localhost: free pass!
  $ip -A INPUT -i lo -j ACCEPT
  $ip -A OUTPUT -o lo -j ACCEPT

  # administration ips: free pass!
  for admin in $admins ; do
      $ip -A INPUT -s $admin -j ACCEPT
      $ip -A OUTPUT -d $admin -j ACCEPT
  done

  # allow ssh access to sshers
  for ssher in $sshers ; do
      $ip -A INPUT -s $ssher -p tcp -m tcp --dport 22 -j ACCEPT
      $ip -A OUTPUT -d $ssher -p tcp -m tcp --sport 22 -j ACCEPT
  done

  # allow access to mysql port to iReport on sugar

  for mysql in $mysqlrs ; do
      $ip -A INPUT -s $mysql -p tcp -m tcp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p tcp -m tcp --sport 3306 -j ACCEPT
      $ip -A INPUT -s $mysql -p udp -m udp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p udp -m udp --sport 3306 -j ACCEPT
  done


  # allowed services
  for service in $tcpservices ; do
      $ip -A INPUT -p tcp -m tcp --dport $service -j ACCEPT
      $ip -A OUTPUT -p tcp -m tcp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done
  for service in $udpservices ; do
      $ip -A INPUT -p udp -m udp --dport $service -j ACCEPT
      $ip -A OUTPUT -p udp -m udp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done

  $ip -A INPUT -j LOG --log-level 4
  # VAS and VGP
  #88 tcp udp
  #389 tcp ldap queries , udp ldap ping
  #464 tcp upd kerberos
  #3268 tcp global catalog access
  for dc in ip.ip.ip.ip ; do # our dc servers for some ldap auth
      vas=88
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $vas -j ACCEPT
      ldap=389
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $ldap -j ACCEPT
      kpasswd=464
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      gca=3268
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $gca -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $gca -j ACCEPT
      vgp=445
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vgp -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vgp -j ACCEPT
  done


  # allow the machine to browse the internet
  $ip -A INPUT -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 443 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

  $ip -A INPUT -p tcp -m tcp --sport 8080 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 8080 -j ACCEPT


  # don't forget the dns...
  $ip -A INPUT -p udp -m udp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT

  # ... neither the ntp... (hora.rediris.es)
  #$ip -A INPUT -s 130.206.3.166 -p udp -m udp --dport 123 -j ACCEPT
  #$ip -A OUTPUT -d 130.206.3.166 -p udp -m udp --sport 123 -j ACCEPT

  $ip -A INPUT -p udp -m udp --dport 123 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --sport 123 -j ACCEPT


  # and last but not least, the snmp access
  for monitor in $snmprs ; do
      $ip -A INPUT -s $monitor -p tcp -m tcp --sport 161 -j ACCEPT   # monitoring service
      $ip -A OUTPUT -d $monitor -p tcp -m tcp --dport 161 -j ACCEPT  # monitoring service
  end
  # outgoing SMTP
  $ip -A INPUT -p tcp -m tcp --sport 25 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT


  # temporary backup if we change from DROP to ACCEPT policies
  $ip -A INPUT -p tcp -m tcp --dport 1:1024 -j DROP
  $ip -A INPUT -p udp -m udp --dport 1:1024 -j DROP


  echo "OK. Check rules with iptables -L -n"

  # end :)

나는 그것을 한동안 사용해 왔으며, 관리가 더 쉬워지면 어떤 종류의 수정이라도 대단히 감사하겠습니다.


TCP를 통해 SNMP (161)를 사용하는 널리 사용되는 도구가 있습니까? 이 규칙은 UDP / 161이어야한다고 생각합니다.
kubanczyk

1

이것은 꽤 좋아 보이지만 조금 더 조일 수 있습니다. -s 플래그는 소스 IP 또는 도메인 이름이며 "-s 198.23.12.32"또는 IP 주소가 소스 IP의 SSH 만 허용하는 모든 것을 추가합니다. CIDR 스타일 표기법 을 사용하여 다양한 소스 IP를 선택할 수도 있습니다 .

거부 된 통화를 기록 할 때는주의해야합니다. 서버의 IP 주소는 봇, 스크립트 키드 등으로 스캔되며 로그 파일은 다소 빠르게 커질 수 있습니다. 방화벽을 차단하려는 누군가와 관련이 있다고 생각되는 특정 문제를 진단하려고하지 않는 한이 옵션을 제거합니다.

의사 IDS를 위해 fail2ban 을 iptables에 연결할 수도 있습니다 . fail2ban은 로그 파일을 스캔하여 시스템으로 강제 침입하려고하면 IP를 차단할 수 있습니다. 예를 들어 특정 IP 주소가 SSH에 5 번 로그인하지 못하면 하루 종일 잠글 수 있습니다. 또한 FTP와 다른 많은 것 (Apache에 부딪히는 잘못된 봇 포함)에서도 작동합니다.


fail2ban 이상 15MB 이상을 절약하기 때문에 실제로 DenyHosts를 사용합니다. 그러나 fail2ban은 더 강력하며 DenyHosts와 같은 SSH뿐만 아니라 많은 응용 프로그램에서 작동합니다. 공격자가 금지 된 것을 감안할 때 여전히 로그 파일이 빨리 채워지는 것에 대해 걱정해야합니까? 파일이 가득 차면 파일을 회전시키는 방법이 있습니까? fail2ban에서 로깅을 비활성화하면 Denyhosts / Fail2ban에 여전히 로그 항목이 스캔됩니까? 또한 소스 옵션은 일부 사람들에게 좋을 것입니다.하지만 기본 규칙 세트를 목표로하고 있기 때문에 많은 사람들이 이동하는 경우 해당 옵션을 사용할 수 없습니다.
Xeoncross

@ Xeoncross : DenyHosts는 김이 나는 더미입니다. 나는 중국에서 끊임없이 침입을 시도하는 한 대의 컴퓨터에서 실행 중이었습니다. 몇 개월 동안 /etc/hosts.deny는 수천 개의 IP를 갖게되었고, 이로 인해 sshd가 박스에서 리소스를 소모하여 단일 CPU 시스템에서 최대 60+의로드를 급증했습니다. 나는 fail2ban로 바꾸었고 결코 뒤돌아 보지 않았다.
hobodave

@hobodave 나는 방금 DenyHosts로 시작했기 때문에 이것이 문제가 될 때 가장 먼저 전환해야 할 것으로 생각합니다.
Xeoncross

1
@Xeoncross iptables 로그를 회전하려면 자신의 logrotate.d 스크립트를 작성할 수 있습니다. /etc/logrotate.d를보고 다른 것을 복사하고 로그 파일 이름을 변경하면 다른 로그 파일과 함께 회전됩니다. logrotate 매뉴얼 페이지는 다양한 옵션을 설명합니다.
Alan Ivey

1

Shorewall을보십시오. 단일 인터페이스 기본 구성이 좋은 출발점이 될 것입니다. 구성하기 쉽고 SSH 및 웹 액세스와 같은 매크로가 있습니다. 방화벽이 종료 될 때 서버를 원하는 수준으로 잠그도록 구성 할 수 있습니다. Shorewall-lite를 사용하면 다른 서버에서 방화벽 빌드를 실행할 수 있습니다. 로깅은 원하는 수준으로 쉽게 구성 할 수 있습니다.

기본 HTTP 서버의 경우 HTTPS를 사용하는 경우 포트 80 및 포트 443에 대한 수신 액세스를 열려고합니다. 몇몇 제한된 주소에서 SSH 수신 액세스가 일반적으로 필요합니다. 발신 액세스도 잠글 수 있습니다. 필요한 서버 및 서비스에 대해서만 방화벽을 엽니 다. 패치를 가져올 채널뿐만 아니라 NTP와 DNS도 열어야합니다.


1

인바운드 트래픽을 중지하고 송신 또는 아웃 바운드 트래픽에 중점을 두지 않는다는 점을 제외하고는 이것이 매우 훌륭한 방화벽이라고 말하고 싶습니다. 대부분의 경우 인바운드 연결만큼 상자에서 아웃 바운드 연결에 집중하는 것이 중요합니다. 불행히도 컴퓨터가 실제로 악용되는 경우 추가 루트 키트 다운로드 또는 명령 및 제어 노드 등에 연결하는 것을 방지 할 수 있으면 좋을 것입니다.

BillThor는 위에서 이에 대해 이야기하기 시작했지만 구체적인 예를 들어 대답하고 있습니다. iptables의 좋은 점 중 하나는 연결 상태를 기억할 수 있다는 것입니다. 트래픽이 많은 사이트에서는 성능에 영향을 줄 수 있지만 http / https에 대한 인바운드 액세스를 변경하여 예를 들어 설정된 연결에 대한 응답 만 허용하거나 특정 권한이없는 사용자를 특별히 제한 할 수 있습니다 사용자가 전혀 아웃 바운드 액세스 할 수 없습니다. 그런 다음 아웃 바운드 규칙에는 관련된 모든 공격이 방지되고 실제로는 상자를 악용하기 위해 2 차 단계를 필요로하는 공격이 느려지는 RELATED, ESTABLISHED 절이 있습니다.

마지막으로, 끝에 REJECT를 추가하는 것보다 iptables 정책 -P DROP을 설정하는 것이 좋습니다. 주로 선호하는 문제이지만 삽입 또는 플러시 / 재설정 대신 기존 규칙으로 체인에 추가 할 때 실수를 줄일 수 있습니다.


그래서로 변경 -A INPUT -j REJECT해야 -A INPUT -P DROP합니까?
Xeoncross
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.