웹사이트 검색

Ubuntu 14.04에서 Iptables로 기본 방화벽 템플릿을 구현하는 방법


소개

방화벽 구현은 서버 보안에서 중요한 단계입니다. 그 중 상당 부분은 네트워크에 트래픽 제한을 적용할 개별 규칙 및 정책을 결정하는 것입니다. iptables와 같은 방화벽을 사용하면 규칙이 적용되는 구조적 프레임워크에 대해 말할 수 있습니다.

이 가이드에서는 보다 복잡한 규칙 집합의 기반이 될 수 있는 방화벽을 구성합니다. 이 방화벽은 주로 합리적인 기본값을 제공하고 쉬운 확장성을 장려하는 프레임워크를 설정하는 데 중점을 둡니다. Ubuntu 14.04 서버에서 이를 시연할 것입니다.

전제 조건

시작하기 전에 구현하려는 방화벽 정책에 대한 기본 개념이 있어야 합니다. 이 가이드를 따라 생각해야 할 몇 가지 사항에 대한 더 나은 아이디어를 얻을 수 있습니다.

따라 하려면 Ubuntu 14.04 서버에 액세스할 수 있어야 합니다. 이 가이드 전체에서 sudo 권한으로 구성된 루트가 아닌 사용자를 사용합니다. Ubuntu 14.04 초기 서버 설정 가이드에서 이러한 유형의 사용자를 구성하는 방법을 알아볼 수 있습니다.

완료되면 아래에서 계속하십시오.

영구 방화벽 서비스 설치

시작하려면 iptables-persistent 패키지를 아직 설치하지 않은 경우 설치해야 합니다. 이렇게 하면 규칙 세트를 저장하고 부팅 시 자동으로 적용할 수 있습니다.

  1. sudo apt-get update
  2. sudo apt-get install iptables-persistent

설치하는 동안 현재 규칙을 저장할 것인지 묻는 메시지가 표시됩니다. 여기에서 "예\라고 말하십시오. 생성된 규칙 파일을 잠시 편집할 것입니다.

이 가이드의 IPv6에 대한 참고 사항

시작하기 전에 IPv4와 IPv6에 대해 간단히 이야기해야 합니다. iptables 명령은 IPv4 트래픽만 처리합니다. IPv6 트래픽의 경우 ip6tables라는 별도의 동반 도구가 사용됩니다. 규칙은 별도의 테이블과 체인에 저장됩니다. iptables-persistent의 경우 IPv4 규칙은 /etc/iptables/rules.v4에서 읽고 쓰고 IPv6 규칙은 /etc/iptables에 보관됩니다. /rules.v6.

이 가이드는 서버에서 IPv6를 적극적으로 사용하지 않는다고 가정합니다. 서비스가 IPv6를 활용하지 않는 경우 이 문서에서 수행할 것처럼 액세스를 완전히 차단하는 것이 더 안전합니다.

기본 방화벽 정책 구현(빠른 방법)

가능한 한 빨리 실행하기 위해 규칙 파일을 직접 편집하여 완성된 방화벽 정책을 복사하고 붙여넣는 방법을 보여드리겠습니다. 그런 다음 일반적인 전략을 설명하고 파일을 수정하는 대신 iptables 명령을 사용하여 이러한 규칙을 구현하는 방법을 보여줍니다.

방화벽 정책 및 프레임워크를 구현하기 위해 /etc/iptables/rules.v4/etc/iptables/rules.v6 파일을 편집합니다. sudo 권한으로 텍스트 편집기에서 rules.v4 파일을 엽니다.

  1. sudo nano /etc/iptables/rules.v4

내부에는 다음과 같은 파일이 표시됩니다.

# Generated by iptables-save v1.4.21 on Tue Jul 28 13:29:56 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Jul 28 13:29:56 2015

내용을 다음으로 바꿉니다.

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

파일을 저장하고 닫습니다.

이 명령을 입력하여 파일의 구문 오류를 테스트할 수 있습니다. 계속하기 전에 표시되는 모든 구문 오류를 수정합니다.

  1. sudo iptables-restore -t /etc/iptables/rules.v4

다음으로 /etc/iptables/rules.v6 파일을 열어 IPv6 규칙을 수정합니다.

  1. sudo nano /etc/iptables/rules.v6

파일의 내용을 아래 구성으로 대체하여 모든 IPv6 트래픽을 차단할 수 있습니다.

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*raw
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*nat
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

*security
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*mangle
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

파일을 저장하고 닫습니다.

구문 오류에 대해 이 파일을 테스트하려면 -t 옵션과 함께 ip6tables-restore 명령을 사용할 수 있습니다.

  1. sudo ip6tables-restore -t /etc/iptables/rules.v6

두 규칙 파일 모두 구문 오류가 보고되지 않으면 다음을 입력하여 규칙을 적용할 수 있습니다.

  1. sudo service iptables-persistent reload

이렇게 하면 파일에 설명된 정책이 즉시 구현됩니다. 현재 사용 중인 iptables 규칙을 나열하여 이를 확인할 수 있습니다.

  1. sudo iptables -S
  2. sudo ip6tables -S

이러한 방화벽 규칙은 부팅할 때마다 다시 적용됩니다. 여전히 로그인할 수 있고 다른 모든 액세스가 차단되어 있는지 테스트하십시오.

일반적인 방화벽 전략에 대한 설명

위의 규칙으로 구성한 기본 방화벽에서 규칙을 추가하거나 제거하도록 쉽게 조정할 수 있는 확장 가능한 프레임워크를 만들었습니다. IPv4 트래픽의 경우 주로 filter 테이블 내의 INPUT 체인과 관련이 있습니다. 이 체인은 서버로 향하는 모든 패킷을 처리합니다. 또한 나가는 모든 트래픽을 허용하고 모든 패킷 전달을 거부했습니다. 이는 이 서버가 다른 호스트의 라우터 역할을 하는 경우에만 적절할 것입니다. 이 가이드에서는 패킷만 필터링하기 때문에 다른 모든 테이블의 패킷을 허용합니다.

일반적으로 우리의 규칙은 기본적으로 들어오는 트래픽을 거부하는 방화벽을 설정합니다. 그런 다음 이 정책에서 제외하려는 서비스 및 트래픽 유형에 대한 예외를 생성합니다.

기본 INPUT 체인에서 우리는 트래픽이 항상 동일한 방식으로 처리될 것이라고 확신하는 몇 가지 일반 규칙을 추가했습니다. 예를 들어, 우리는 \무효\로 간주되는 패킷을 항상 거부하고 로컬 루프백 인터페이스 및 설정된 연결과 관련된 데이터에 대한 트래픽을 항상 허용하기를 원할 것입니다.

그런 다음 사용 중인 프로토콜을 기반으로 트래픽을 일치시키고 프로토콜별 체인에 섞습니다. 이러한 프로토콜별 체인은 특정 서비스에 대한 트래픽을 일치시키고 허용하는 규칙을 유지하기 위한 것입니다. 이 예에서 우리가 허용하는 유일한 서비스는 TCP 체인의 SSH입니다. HTTP(S) 서버와 같은 다른 서비스를 제공하는 경우 여기에도 예외를 추가할 수 있습니다. 이러한 체인은 대부분의 사용자 정의의 초점이 됩니다.

일반 규칙 또는 프로토콜별 서비스 규칙과 일치하지 않는 모든 트래픽은 INPUT 체인의 마지막 몇 가지 규칙에 의해 처리됩니다. 방화벽에 대한 기본 정책을 DROP로 설정하여 규칙을 통과하는 패킷을 거부합니다. 그러나 INPUT 체인 끝에 있는 규칙은 패킷을 거부하고 해당 포트에서 실행 중인 서비스가 없을 경우 서버가 응답하는 방식을 모방한 메시지를 클라이언트에 보냅니다.

IPv6 트래픽의 경우 모든 트래픽을 삭제합니다. 우리 서버는 이 프로토콜을 사용하지 않으므로 트래픽에 전혀 관여하지 않는 것이 가장 안전합니다.

(선택사항) 네임서버 업데이트

모든 IPv6 트래픽을 차단하면 서버가 인터넷에서 문제를 해결하는 방식을 방해할 수 있습니다. 예를 들어 이것은 APT를 사용하는 방법에 영향을 미칠 수 있습니다.

apt-get update를 실행하려고 할 때 다음과 같은 오류가 발생하는 경우:

Err http://security.ubuntu.com trusty-security InRelease
  
Err http://security.ubuntu.com trusty-security Release.gpg
  Could not resolve 'security.ubuntu.com'
  
. . .

APT가 다시 작동하도록 하려면 이 섹션을 따라야 합니다.

먼저 네임서버를 외부 네임서버로 설정합니다. 이 예에서는 Google의 네임서버를 사용합니다. 편집을 위해 /etc/network/interfaces를 엽니다.

  1. sudo nano /etc/network/interfaces

다음과 같이 dns-nameservers 줄을 업데이트합니다.

. . .
iface eth0 inet6 static
        address 2604:A880:0800:0010:0000:0000:00B2:0001
        netmask 64
        gateway 2604:A880:0800:0010:0000:0000:0000:0001
        autoconf 0
        dns-nameservers 8.8.8.8 8.8.4.4

네트워크 설정을 새로 고칩니다.

  1. sudo ifdown eth0 && sudo ifup eth0

예상 출력은 다음과 같습니다.

RTNETLINK answers: No such process
Waiting for DAD... Done

다음으로 IPv4를 사용할 수 있을 때 강제 적용하는 새 방화벽 규칙을 만듭니다. 이 새 파일을 만듭니다.

  1. sudo nano /etc/apt/apt.conf.d/99force-ipv4

다음 한 줄을 파일에 추가합니다.

Acquire::ForceIPv4 "true";

파일을 저장하고 닫습니다. 이제 APT를 사용할 수 있습니다.

IPTables 명령을 사용하여 방화벽 구현

이제 우리가 구축한 정책의 일반적인 개념을 이해했으므로 iptables 명령을 사용하여 이러한 규칙을 만드는 방법을 살펴보겠습니다. 위에서 지정한 것과 동일한 규칙으로 끝나지만 반복적으로 규칙을 추가하여 정책을 만들 것입니다. iptables는 각 규칙을 즉시 적용하기 때문에 규칙 순서가 매우 중요합니다(패킷을 거부하는 규칙은 끝까지 둡니다).

방화벽 재설정

먼저 명령줄에서 정책을 구축하는 방법을 확인할 수 있도록 방화벽 규칙을 재설정합니다. 다음을 입력하여 모든 규칙을 플러시할 수 있습니다.

  1. sudo service iptables-persistent flush

다음을 입력하여 규칙이 재설정되었는지 확인할 수 있습니다.

  1. sudo iptables -S

filter 테이블의 규칙이 사라지고 기본 정책이 모든 체인에서 ACCEPT로 설정되어 있는지 확인해야 합니다.

output
-P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT

프로토콜별 체인 만들기

모든 프로토콜별 체인을 생성하는 것부터 시작하겠습니다. 노출하려는 서비스에 대한 거부 정책에 대한 예외를 생성하는 규칙을 유지하는 데 사용됩니다. UDP 트래픽용, TCP용 및 ICMP용으로 하나씩 생성합니다.

  1. sudo iptables -N UDP
  2. sudo iptables -N TCP
  3. sudo iptables -N ICMP

바로 진행하여 SSH 트래픽에 대한 예외를 추가할 수 있습니다. SSH는 TCP를 사용하므로 포트 22로 향하는 TCP 트래픽을 TCP 체인으로 허용하는 규칙을 추가합니다.

  1. sudo iptables -A TCP -p tcp --dport 22 -j ACCEPT

추가 TCP 서비스를 추가하려는 경우 포트 번호를 바꾼 명령을 반복하여 지금 수행할 수 있습니다.

범용 수락 및 거부 규칙 만들기

들어오는 모든 트래픽이 필터링을 시작하는 INPUT 체인에서 범용 규칙을 추가해야 합니다. 이들은 위험이 낮은 트래픽(로컬 트래픽 및 이미 확인한 연결과 관련된 트래픽)을 수락하고 분명히 유용하지 않은 트래픽(잘못된 패킷)을 삭제하여 방화벽의 기준을 설정하는 상식적인 규칙입니다.

먼저 설정된 연결의 일부이거나 설정된 연결과 관련된 모든 트래픽을 허용하는 예외를 만듭니다.

  1. sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

이 규칙은 내부 추적을 제공하는 conntrack 확장을 사용하여 iptables가 개별적이고 관련 없는 스트림 대신 더 큰 연결의 일부로 패킷을 평가하는 데 필요한 컨텍스트를 갖도록 합니다. 패킷. TCP는 연결 기반 프로토콜이므로 설정된 연결이 상당히 잘 정의되어 있습니다. UDP 및 기타 연결 없는 프로토콜의 경우 설정된 연결은 응답을 본 트래픽을 나타냅니다(원래 패킷의 소스는 응답 패킷의 대상이 되고 그 반대도 마찬가지임). 관련 연결은 기존 연결과 관련하여 시작된 새로운 연결을 의미합니다. 여기서 고전적인 예는 이미 설정된 FTP 제어 연결과 관련된 FTP 데이터 전송 연결입니다.

또한 로컬 루프백 인터페이스에서 발생하는 모든 트래픽을 허용하려고 합니다. 이것은 서버에서 생성되고 서버로 향하는 트래픽입니다. 호스트의 서비스에서 서로 통신하는 데 사용됩니다.

  1. sudo iptables -A INPUT -i lo -j ACCEPT

마지막으로 모든 유효하지 않은 패킷을 거부하려고 합니다. 여러 가지 이유로 패킷이 유효하지 않을 수 있습니다. 존재하지 않는 연결을 참조하거나 존재하지 않는 인터페이스, 주소 또는 포트로 향하거나 단순히 형식이 잘못되었을 수 있습니다. 어쨌든 잘못된 패킷을 처리할 수 있는 적절한 방법이 없고 악의적인 활동을 나타낼 수 있으므로 모든 유효하지 않은 패킷을 삭제합니다.

  1. sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

프로토콜별 체인에 대한 점프 규칙 만들기

지금까지 우리는 INPUT 체인에서 몇 가지 일반적인 규칙과 프로토콜별 체인 내에서 허용되는 특정 서비스에 대한 몇 가지 규칙을 만들었습니다. 그러나 현재 트래픽은 INPUT 체인으로 들어오고 프로토콜별 체인에 도달할 방법이 없습니다.

INPUT 체인의 트래픽을 적절한 프로토콜별 체인으로 보내야 합니다. 프로토콜 유형을 일치시켜 올바른 체인으로 보낼 수 있습니다. 또한 패킷이 새 연결을 나타내는지 확인합니다(설정된 연결 또는 관련 연결은 이미 이전에 처리되어야 함). TCP 패킷의 경우 패킷이 TCP 연결을 시작하는 유일한 유효한 유형인 SYN 패킷이라는 추가 요구 사항을 추가합니다.

  1. sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
  2. sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
  3. sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

나머지 모든 트래픽 거부

프로토콜별 체인으로 전달된 패킷이 내부 규칙과 일치하지 않는 경우 제어가 INPUT 체인으로 다시 전달됩니다. 이 지점에 도달하는 모든 것은 방화벽에서 허용되지 않아야 합니다.

클라이언트에 응답 메시지를 보내는 REJECT 대상을 사용하여 트래픽을 거부합니다. 이를 통해 클라이언트가 패킷을 일반 폐쇄 포트로 보내려고 시도하는 경우 제공되는 응답을 모방할 수 있도록 아웃바운드 메시징을 지정할 수 있습니다. 응답은 클라이언트에서 사용하는 프로토콜에 따라 다릅니다.

닫힌 UDP 포트에 도달하려고 시도하면 ICMP "port unreachable\ 메시지가 표시됩니다. 다음을 입력하여 이를 모방할 수 있습니다.

  1. sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable

닫힌 포트에서 TCP 연결을 시도하면 TCP RST 응답이 발생합니다.

  1. sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

다른 모든 패킷의 경우 서버가 해당 유형의 패킷에 응답하지 않음을 나타내기 위해 ICMP "protocol unreachable\ 메시지를 보낼 수 있습니다.

  1. sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

기본 정책 조정

우리가 추가한 마지막 세 가지 규칙은 INPUT 체인에 남아 있는 모든 트래픽을 처리해야 합니다. 그러나 예방책으로 기본 정책을 DROP로 설정해야 합니다. 또한 이 서버가 다른 머신에 대한 라우터로 구성되지 않은 경우 FORWARD 체인에서 이 정책을 설정해야 합니다.

  1. sudo iptables -P INPUT DROP
  2. sudo iptables -P FORWARD DROP

정책을 DROP로 설정한 상태에서 sudo iptables -Fiptables를 지우면 현재 SSH 연결이 끊어집니다! sudo iptables-persistent flush를 사용한 플러시는 기본 정책도 재설정하므로 규칙을 지우는 더 좋은 방법입니다.

모든 트래픽을 삭제하는 IPv6 정책과 일치시키기 위해 다음 ip6tables 명령을 사용할 수 있습니다.

  1. sudo ip6tables -P INPUT DROP
  2. sudo ip6tables -P FORWARD DROP
  3. sudo ip6tables -P OUTPUT DROP

이것은 상당히 밀접하게 설정된 규칙을 복제해야 합니다.

IPTables 규칙 저장

이 시점에서 방화벽 규칙을 테스트하고 정상적인 액세스를 방해하지 않으면서 차단하려는 트래픽을 차단하는지 확인해야 합니다. 규칙이 올바르게 작동하는 것에 만족하면 부팅 시 시스템에 자동으로 적용되도록 규칙을 저장할 수 있습니다.

다음을 입력하여 현재 규칙(IPv4 및 IPv6 모두)을 저장합니다.

  1. sudo service iptables-persistent save

이렇게 하면 /etc/iptables/rules.v4/etc/iptables/rules.v6 파일을 명령줄에서 만든 정책으로 덮어씁니다.

결론

이 가이드에 따라 방화벽 규칙을 구성 파일에 직접 붙여넣거나 수동으로 적용하고 명령줄에 저장하면 좋은 시작 방화벽 구성을 만들 수 있습니다. 사용 가능하게 하려는 서비스에 대한 액세스를 허용하려면 개별 규칙을 추가해야 합니다.

이 가이드에 설정된 프레임워크를 사용하면 쉽게 조정할 수 있고 기존 정책을 명확히 하는 데 도움이 될 수 있습니다. 몇 가지 인기 있는 서비스로 방화벽 정책을 구축하는 방법을 알아보려면 다른 가이드를 확인하세요.

  • Iptables Essentials: 일반 방화벽 규칙 및 명령
  • 서버 간 트래픽을 보호하기 위해 Iptables 방화벽을 설정하는 방법
  • Iptables를 사용하여 Linux 게이트웨이를 통해 포트를 전달하는 방법
  • Nmap 및 Tcpdump로 방화벽 구성을 테스트하는 방법