Ubuntu 14.04에서 Iptables를 사용하여 방화벽을 설정하는 방법
소개
좋은 방화벽을 설정하는 것은 최신 운영 체제를 보호하기 위한 필수 단계입니다. 대부분의 Linux 배포판에는 방화벽을 구성하는 데 사용할 수 있는 몇 가지 다른 방화벽 도구가 함께 제공됩니다. 이 가이드에서는 iptables 방화벽을 다룰 것입니다.
Iptables는 기본적으로 대부분의 Linux 배포판에 포함된 표준 방화벽입니다(nftables라는 최신 변형이 이를 대체하기 시작함). 실제로 Linux 네트워크 스택을 조작할 수 있는 커널 수준 netfilter 후크의 프런트 엔드입니다. 네트워킹 인터페이스를 통과하는 각 패킷을 일련의 규칙에 대해 일치시켜 수행할 작업을 결정하는 방식으로 작동합니다.
이전 가이드에서 원치 않는 트래픽을 차단하기 위해 iptables 규칙이 작동하는 방법을 배웠습니다. 이 가이드에서는 Ubuntu 14.04 서버에 대한 기본 규칙 집합을 만드는 방법을 보여 주는 실용적인 예로 이동합니다. 결과 방화벽은 SSH 및 HTTP 트래픽을 허용합니다.
참고: 이 자습서에서는 IPv4 보안을 다룹니다. Linux에서 IPv6 보안은 IPv4와 별도로 유지됩니다. 예를 들어 "iptables\는 IPv4 주소에 대한 방화벽 규칙만 유지하지만 IPv6 네트워크 주소에 대한 방화벽 규칙을 유지하는 데 사용할 수 있는 "ip6tables\라는 IPv6 대응 항목이 있습니다.
VPS가 IPv6용으로 구성된 경우 적절한 도구를 사용하여 IPv4 및 IPv6 네트워크 인터페이스를 모두 보호해야 합니다. IPv6 도구에 대한 자세한 내용은 이 가이드를 참조하십시오. Linux VPS에서 IPv6을 사용하도록 도구를 구성하는 방법
전제 조건
이 자습서를 사용하기 전에 서버에 설정된 별도의 비루트 수퍼유저 계정(sudo 권한이 있는 사용자)이 있어야 합니다. 이를 설정해야 하는 경우 Ubuntu 14.04를 사용한 초기 서버 설정 가이드를 따르십시오.
기본 iptables 명령
이제 iptables 개념을 잘 이해했으므로 복잡한 규칙 세트를 형성하고 일반적으로 iptables 인터페이스를 관리하는 데 사용되는 기본 명령을 다루어야 합니다.
먼저 iptables 명령은 루트 권한으로 실행해야 한다는 점을 알고 있어야 합니다. 즉, 루트로 로그인하거나 su
또는 sudo -i
를 사용하여 루트 셸을 얻거나 모든 명령 앞에 sudo
를 붙여야 합니다. sudo
는 우분투 시스템에서 선호되는 방법이므로 이 가이드에서 사용할 것입니다.
좋은 출발점은 iptables에 대해 구성된 현재 규칙을 나열하는 것입니다. -L
플래그를 사용하여 이를 수행할 수 있습니다.
- sudo iptables -L
Output:Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
보시다시피 세 가지 기본 체인(INPUT, OUTPUT 및 FORWARD)이 있습니다. 또한 각 체인의 기본 정책을 볼 수 있습니다(각 체인에는 기본 정책으로 ACCEPT가 있음). 일부 열 머리글도 표시되지만 실제 규칙은 표시되지 않습니다. 이는 Ubuntu가 기본 규칙 세트와 함께 제공되지 않기 때문입니다.
대신 -S
플래그를 사용하여 각 규칙 및 정책을 활성화하는 데 필요한 명령을 반영하는 형식으로 출력을 볼 수 있습니다.
- sudo iptables -S
Output:-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
구성을 복제하려면 sudo iptables
다음에 출력의 각 행을 입력하기만 하면 됩니다. (구성에 따라 원격으로 연결된 경우 실제로 약간 더 복잡할 수 있으므로 현재 연결을 포착하고 허용하는 규칙이 적용되기 전에 기본 삭제 정책을 도입하지 않습니다.)
규칙이 있는 경우 이를 폐기하고 다시 시작하려면 다음을 입력하여 현재 규칙을 플러시할 수 있습니다.
- sudo iptables -F
여기서 다시 한 번 기본 정책이 중요합니다. 모든 규칙이 체인에서 삭제되는 동안 기본 정책은 이 명령으로 변경되지 않습니다. 즉, 원격으로 연결된 경우 규칙을 플러시하기 전에 INPUT 및 OUTPUT 체인의 기본 정책이 ACCEPT로 설정되어 있는지 확인해야 합니다. 다음을 입력하면 됩니다.
- sudo iptables -P INPUT ACCEPT
- sudo iptables -P OUTPUT ACCEPT
- sudo iptables -F
그런 다음 연결을 명시적으로 허용하는 규칙을 설정한 후 기본 드롭 정책을 다시 DROP으로 변경할 수 있습니다. 잠시 후에 그 방법을 살펴보겠습니다.
첫 번째 규칙 만들기
방화벽 정책 구축을 시작할 것입니다. 위에서 말했듯이 들어오는 트래픽이 전송되는 유입경로인 INPUT 체인과 함께 작업할 것입니다. 위에서 조금 언급한 규칙, 즉 현재 SSH 연결을 명시적으로 수락하는 규칙부터 시작하겠습니다.
필요한 전체 규칙은 다음과 같습니다.
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
이것은 매우 복잡해 보일 수 있지만 구성 요소를 살펴보면 대부분 이해가 될 것입니다.
- -A 입력:
-A
플래그는 체인의 끝에 규칙을 추가합니다. 이것은 iptables에게 우리가 새로운 규칙을 추가하고 싶고, 그 규칙을 체인의 끝에 추가하기를 원하며, 우리가 작업하고자 하는 체인이 INPUT 체인이라는 것을 알려주는 명령의 일부입니다.\n - -m conntrack: iptables에는 핵심 기능 세트가 있지만 추가 기능을 제공하는 확장 또는 모듈 세트도 있습니다.\n명령의 이 부분에서 우리는
conntrack
모듈이 제공하는 기능에 액세스할 수 있기를 원한다고 명시하고 있습니다. 이 모듈은 패킷과 이전 연결의 관계를 기반으로 결정을 내리는 데 사용할 수 있는 명령에 대한 액세스를 제공합니다.\n - –ctstate:
conntrack
모듈을 호출하여 사용할 수 있는 명령 중 하나입니다. 이 명령을 사용하면 이전에 본 패킷과 어떻게 관련되어 있는지에 따라 패킷을 일치시킬 수 있습니다.\n기존 연결의 일부인 패킷을 허용하기 위해ESTABLISHED
값을 전달합니다. 설정된 연결과 관련된 패킷을 허용하기 위해RELATED
값을 전달합니다. 이것은 현재 SSH 세션과 일치하는 규칙 부분입니다.\n - -j ACCEPT: 일치하는 패킷의 대상을 지정합니다. 여기서 우리는 iptables에게 이전 기준과 일치하는 패킷을 수락하고 허용해야 한다고 알려줍니다.\n
DROP 규칙에 도달하기 전에 이미 사용하고 있는 연결이 일치하고 수락되고 체인에서 제거되는지 확인하기 위해 이 규칙을 시작 부분에 두었습니다.
규칙을 나열하면 변경 사항을 볼 수 있습니다.
- sudo iptables -L
Output:Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
이제 일반적인 구문을 알았으므로 연결을 수락하려는 경우를 더 추가하여 계속하겠습니다.
기타 필요한 연결 수락
우리는 iptables에게 이미 열려 있는 모든 연결을 열어두고 해당 연결과 관련된 새 연결을 허용하도록 지시했습니다. 그러나 이러한 기준을 충족하지 않는 새 연결을 수락하려는 경우 설정할 몇 가지 규칙을 만들어야 합니다.
우리는 특별히 두 개의 포트를 열어두기를 원합니다. 우리는 SSH 포트를 열린 상태로 유지하려고 합니다(이 안내서에서는 이것이 기본값 22라고 가정합니다. SSH 구성에서 이를 변경한 경우 여기에서 값을 수정하십시오). 또한 이 컴퓨터가 기본 포트 80에서 웹 서버를 실행하고 있다고 가정합니다. 그렇지 않은 경우 해당 규칙을 추가할 필요가 없습니다.
이 규칙을 추가하는 데 사용할 두 줄은 다음과 같습니다.
- sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
- sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
보시다시피, 이들은 첫 번째 규칙과 매우 유사하지만 아마도 더 간단할 것입니다. 새로운 옵션은 다음과 같습니다.
- -p tcp: 이 옵션은 사용 중인 프로토콜이 TCP인 경우 패킷을 일치시킵니다. 이는 신뢰할 수 있는 통신을 허용하기 때문에 대부분의 애플리케이션에서 사용되는 연결 기반 프로토콜입니다.
- –dport: 이 옵션은
-p tcp
플래그가 지정된 경우 사용할 수 있습니다. 일치하는 패킷에 대해 대상 포트를 일치시키는 추가 요구 사항을 제공합니다. 첫 번째 규칙은 포트 22로 향하는 TCP 패킷과 일치하고 두 번째 규칙은 포트 80을 가리키는 TCP 트래픽과 일치합니다.
서버가 올바르게 작동할 수 있도록 하는 데 필요한 승인 규칙이 하나 더 있습니다. 종종 컴퓨터의 서비스는 네트워크 패킷을 서로 전송하여 서로 통신합니다. 그들은 트래픽을 다른 컴퓨터가 아닌 자신에게 다시 보내는 루프백 장치
라는 의사 네트워크 인터페이스를 활용하여 이를 수행합니다.
따라서 한 서비스가 포트 4555에서 연결을 수신하는 다른 서비스와 통신하려는 경우 루프백 장치의 포트 4555로 패킷을 보낼 수 있습니다. 많은 프로그램의 올바른 작동에 필수적이기 때문에 이러한 유형의 동작이 허용되기를 원합니다.
추가해야 할 규칙은 다음과 같습니다.
- sudo iptables -I INPUT 1 -i lo -j ACCEPT
이것은 다른 명령과 약간 다르게 보입니다. 무엇을 하는지 살펴보겠습니다.
- -I INPUT 1:
-I
플래그는 iptables에게 규칙을 삽입하라고 지시합니다. 이것은 끝에 규칙을 추가하는-A
플래그와 다릅니다.-I
플래그는 체인과 새 규칙을 삽입하려는 규칙 위치를 취합니다.\n이 경우 이 규칙을 INPUT 체인의 첫 번째 규칙으로 추가합니다. 이렇게 하면 나머지 규칙이 다운됩니다. 이것이 기본적이고 후속 규칙의 영향을 받지 않아야 하기 때문에 맨 위에 놓기를 원합니다.\n - -i lo: 패킷이 사용하는 인터페이스가 "lo\ 인터페이스인 경우 규칙의 이 구성 요소가 일치합니다. "lo\ 인터페이스는 루프백 장치의 다른 이름입니다. 이는 통신을 위해 해당 인터페이스를 사용하는 모든 패킷(서버를 위해 서버에서 생성된 패킷)을 수락해야 함을 의미합니다.\n
현재 규칙을 보려면 -S
플래그를 사용해야 합니다. 이는 -L
플래그에 방금 추가한 규칙의 중요한 부분인 규칙이 연결된 인터페이스와 같은 일부 정보가 포함되어 있지 않기 때문입니다.
- sudo iptables -S
Output:-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
삭제 규칙 구현
이제 특정 기준에 따라 패킷을 명시적으로 수락하는 네 가지 별도의 규칙이 있습니다. 그러나 현재 Google 방화벽은 아무것도 차단하지 않습니다.
패킷이 INPUT 체인에 들어가고 우리가 만든 네 가지 규칙 중 하나와 일치하지 않으면 어쨌든 패킷을 수락하는 기본 정책으로 전달됩니다. 우리는 이것을 바꿀 필요가 있습니다.
이를 수행할 수 있는 두 가지 방법이 있지만 몇 가지 매우 중요한 차이점이 있습니다.
이를 수행할 수 있는 첫 번째 방법은 INPUT 체인의 기본 정책을 수정하는 것입니다. 다음을 입력하면 됩니다.
- sudo iptables -P INPUT DROP
이렇게 하면 INPUT 체인을 통과하는 모든 패킷을 잡아서 드롭합니다. 이것이 우리가 기본 삭제 정책이라고 부르는 것입니다. 이러한 유형의 디자인이 의미하는 것 중 하나는 규칙이 플러시되는 경우 패킷 삭제로 대체된다는 것입니다.
이것은 더 안전할 수 있지만 서버에 액세스하는 다른 방법이 없는 경우 심각한 결과를 초래할 수도 있습니다. DigitalOcean을 사용하면 웹 콘솔을 통해 로그인하여 이러한 상황이 발생하는 경우 서버에 액세스할 수 있습니다. 웹 콘솔은 가상 로컬 연결 역할을 하므로 iptables 규칙이 영향을 미치지 않습니다.
규칙이 덤프되는 경우 서버가 자동으로 모든 연결을 끊도록 할 수 있습니다. 이렇게 하면 서버가 활짝 열려 있는 것을 방지할 수 있습니다. 이것은 또한 원하는 대로 패킷을 계속 삭제하면서 체인의 맨 아래에 규칙을 쉽게 추가할 수 있음을 의미합니다.
다른 접근 방식은 체인에 대한 기본 정책을 수락으로 유지하고 나머지 모든 패킷을 체인 자체의 맨 아래로 삭제하는 규칙을 추가하는 것입니다.
위의 INPUT 체인에 대한 기본 정책을 변경한 경우 다음을 입력하여 따라가도록 다시 설정할 수 있습니다.
- sudo iptables -P INPUT ACCEPT
이제 나머지 패킷을 모두 삭제하는 규칙을 체인 맨 아래에 추가할 수 있습니다.
- sudo iptables -A INPUT -j DROP
정상 작동 조건에서의 결과는 기본 드롭 정책과 정확히 동일합니다. 이 규칙은 도달하는 나머지 모든 패킷을 일치시키는 방식으로 작동합니다. 이렇게 하면 패킷이 기본 정책에 도달하기 위해 체인을 통해 결코 드롭되지 않습니다.
기본적으로 트래픽을 허용하는 기본 정책을 유지하는 데 사용됩니다. 이렇게 하면 문제가 발생하여 규칙이 삭제되더라도 네트워크를 통해 시스템에 계속 액세스할 수 있습니다. 이는 빈 체인에 적용될 정책을 변경하지 않고 기본 동작을 구현하는 방법입니다.
물론 이것은 또한 체인의 끝에 추가하려는 추가 규칙이 삭제 규칙 앞에 추가되어야 한다는 것을 의미합니다. 삭제 규칙을 일시적으로 제거하여 이 작업을 수행할 수 있습니다.
- sudo iptables -D INPUT -j DROP
- sudo iptables -A INPUT new_rule_here
- sudo iptables -A INPUT -j DROP
또는 줄 번호를 지정하여 체인의 끝(단, 드롭 이전)에 필요한 규칙을 삽입할 수 있습니다. 라인 번호 4에 규칙을 삽입하려면 다음을 입력할 수 있습니다.
- sudo iptables -I INPUT 4 new_rule_here
각 규칙의 줄 번호를 아는 데 문제가 있는 경우 다음을 입력하여 iptables에 규칙 번호를 지정하도록 지시할 수 있습니다.
- sudo iptables -L --line-numbers
Output:Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere
2 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
3 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
4 ACCEPT tcp -- anywhere anywhere tcp dpt:http
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
이것은 적절한 위치에 규칙을 추가하고 있는지 확인하는 데 도움이 될 수 있습니다.
Iptables 규칙 나열 및 삭제
iptables 규칙 나열 및 삭제에 대한 자세한 내용을 알아보려면 Iptables 방화벽 규칙을 나열하고 삭제하는 방법 자습서를 확인하십시오.
Iptables 구성 저장
기본적으로 iptables에 추가하는 규칙은 일시적입니다. 즉, 서버를 다시 시작하면 iptables 규칙이 사라집니다.
이것은 실제로 일부 사용자를 위한 기능입니다. 실수로 서버에서 자신을 잠근 경우 다시 들어갈 수 있는 방법을 제공하기 때문입니다. 그러나 대부분의 사용자는 생성한 규칙을 자동으로 저장하고 서버가 시작될 때 로드하는 방법을 원할 것입니다.
몇 가지 방법이 있지만 가장 쉬운 방법은 iptables-persistent
패키지를 사용하는 것입니다. Ubuntu의 기본 리포지토리에서 다운로드할 수 있습니다.
- sudo apt-get update
- sudo apt-get install iptables-persistent
설치하는 동안 현재 규칙을 자동으로 로드할 것인지 묻는 메시지가 표시됩니다. 현재 구성에 만족하고 독립적인 SSH 연결을 만드는 기능을 테스트한 경우 현재 규칙을 저장하도록 선택할 수 있습니다.
또한 구성한 IPv6 규칙을 저장할 것인지 묻습니다. 이들은 거의 동일한 방식으로 IPv6 패킷의 흐름을 제어하는 ip6tables
라는 별도의 유틸리티를 통해 구성됩니다.
설치가 완료되면 부팅 시 실행되도록 구성된 iptables-persistent
라는 새 서비스가 제공됩니다. 이 서비스는 규칙에 로드되고 서버가 시작될 때 규칙을 적용합니다.
업데이트 저장
방화벽을 업데이트하고 변경 사항을 보존하려면 iptables 규칙을 저장하여 영구적으로 유지해야 합니다.
다음 명령을 사용하여 방화벽 규칙을 저장하십시오.
- sudo invoke-rc.d iptables-persistent save
결론
이제 요구 사항을 해결하는 방화벽을 개발할 수 있는 좋은 출발점이 있어야 합니다. 더 쉬울 수 있는 다른 많은 방화벽 유틸리티가 있지만 iptables
는 기본 netfilter 구조의 일부를 노출하고 많은 시스템에 존재하기 때문에 좋은 학습 도구입니다.
iptables로 네트워크를 보호하는 방법에 대해 자세히 알아보려면 다음 자습서를 확인하십시오.
- Ubuntu 14.04에서 Iptables로 기본 방화벽 템플릿을 구현하는 방법
- Iptables Essentials: 일반 방화벽 규칙 및 명령
- 서버 간 트래픽을 보호하기 위해 Iptables 방화벽을 설정하는 방법
- Iptables 및 Netfilter 아키텍처에 대한 심층 분석
- Nmap 및 Tcpdump로 방화벽 구성을 테스트하는 방법