강좌
클라우드/리눅스에 관한 강좌입니다.
해킹&보안 분류

SSH 서비스 허용을 위한 iptables 필터링 규칙 설정

작성자 정보

  • 관리자 작성
  • 작성일

컨텐츠 정보

본문

SSH 서비스 허용을 위한 iptables 필터링 규칙 설정







 

이전에는 원격 관리를 위해 telnet을 많이 사용하였지만 만약 스니핑이 작동할 경우에는 telnet 접속 시 입력한 아이디, 암호뿐만 아니라 입력한 명령어 등이 그대로 유출될 수 있는 위험이 있어 최근에는 telnet에 대한 대안으로 세션을 암호화한 프로그램인 ssh를 많이 사용하고 있는 추세이다.

 

 

 

 

ssh는 기본적으로 tcp 22번 포트를 사용하므로 22번 포트에 대한 룰을 설정해 주면 된다.

 

 

 

 

물론 다른 포트를 사용한다면 해당 포트를 지정해 주도록 한다.

 

아래는 ssh가 작동하는 port의 예인데, ssh 서버는 22번을, 클라이언트는 1024 이후의 임의의 포트를 사용하므로, 각각의 포트를 허용해 주면 된다.

 

 

 

 

 

 

클라이언트 1024: ------ 요청 --------> 22 서버

            1024: <----- 응답 -------- 22


 

# 외부에서 방화벽 서버의 ssh 포트로의 접근 허용

 

$IPTABLES -A INPUT -p TCP -s $ALLOWED_IP --sport 1024:65535 --dport 22 -m state --state NEW -j ACCEPT

$IPTABLES -A OUTPUT -p TCP ! --syn --sport 22 -d $ALLOWED_IP --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT




위는 방화벽을 기준으로 보았을 때 외부에서 방화벽의 22번 포트로 들어오는 패킷과 이에 대한 응답으로 나가는 패킷 모두를 허용해 준예이다.

 

 

 

 

이미 알고 있듯이 tcp는 본격적인 데이터 교환을 하기 전에 3 way handshake라는 과정을 거쳐 먼저 송수신 관계를 확인한 후 데이터를 교환하므로 inbound 트래픽과 outbound 트래픽 모두를 허용해 주어야 하며 그렇지 않고 어느 한 쪽만 허용해 줄 경우에는 접속이 되지 않게 된다.

 

 

 

 

왜냐하면 기본정책을 DROP으로 하였을 경우 별도로 허용하지 않은 트래픽은 모두 차단되기 때문이다.

 

 

 

 

여기에서 $ALLOWED_IP라는 변수에 22ssh 포트에 대한 접근을 허용할 IP 또는 IP 대역을 입력해 주면 되고, 모든 IP에서의 ssh 접근을 허용하려면 이 변수에 0/0으로 기입하거나 아예 -s $ALLOWED_IP 부분을 빼면 된다.

 

 

 

 

0/0 또는 0.0.0.0/0anywhere 즉 모든 IP 주소를 의미한다.

 

두 번째 OUTPUT 트래픽을 허용한 것은 위의 그림을 참고하거나 외부에서의 SYN 패킷 요청에 대해 SYN+ACK로 응답한 프로세스를 생각해 보면 된다.

 

 

 

 

이때는 처음 요청에 대한 응답이므로 소스 포트는 22번이 되고 목적지 포트는 22번 포트로 접근 시도한 클라이언트의 포트가 될 것이다.

 

 

 

 

그리고 요청(SYN)에 대한 응답(SYN+ACK)이므로 SYN패킷이 아니라고 설정(! --syn)하였으며 물론 이 설정은 빼도 관계없다.

 

 

 

 

아래 tcpdump로 잡은 패킷이나 3 way handshake 그림을 보면 룰 설정이 그리 어렵지 않다는 것을 알게 될 것이다.

 

 

 

 

첫 번째 패킷은 SYN, 두 번째 패킷은 SYN/ACK임을 알 수 있다.

 

10:24:21.406722 eth0 < client.com.55817 > server.com.ssh: S 2910975826:2910975826(0) win 5840 <mss 1460> (DF) [tos 0x10]

10:24:21.406817 eth0 > server.com.ssh > client.com.55817: S 2960486297:2960486297(0) ack 2910975827 win 5840 <mss 1460> (DF)

 

그리고 앞에서 지정한 첫 번째 INPUT 트래픽에서 상태 추적이 NEW인 것만 허용했으므로 이후의 트래픽은 차단되지 않을까 생각할지 모르겠다.

 

 

 

 

하지만 이미 앞부분에서 프로토콜이나 포트와 관계없이 ESTABLISHED, RELATED에 대해서는 INPUT, OUTPUT 모두 허용했다는 것을 기억하면 이해가 될 것이다.

 

 

 

 

, SYN 연결 요청 및 SYN/ACK 응답 이후에는 모두 ESTABLISHED 또는 RELATED이므로 해당 트래픽이 허용되는 것이다.

 

 

 

 

사실상 두 번째 룰인 OUTPUT은 상태 추적이 ESTABLISHED인데, OUTPUT ESTABLISHED는 이미 앞에서 허용하는 설정을 했고, 더군다나 OUTPUT의 기본정책에서 허용했다면 별도로 언급하지 않아도 된다.

 

 

 

 

만약 앞에서 ESTABLISHED, RELATED를 미리 허용하지 않았다면 INPUT에서 “-m state --state NEW -j ACCEPT”대신 “-m state --stateNEW,ESTABLISHED -j ACCEPT”와 같이 설정해 주어도 된다.

그리고 패킷의 SYNSYN/ACK에 대해서만 설명했지만 이후에 클라이언트와 서버가 통신하는 트래픽은 tcp flag만 다를 뿐 사용되는 포트는 항상 동일(좌측은 1024:이후포트 우측은 22번 포트)하므로 만약 상태추적을 사용하지 않는다면 아래와 같이 포트번호만 명시해도 된다.

 

 

 

 

 

$IPTABLES -A INPUT -p TCP -s $ALLOWED_IP --sport 1024:65535 --dport 22 -j ACCEPT

$IPTABLES -A OUTPUT -p TCP ! --syn --sport 22 -d $ALLOWED_IP --dport 1024:65535 -j ACCEPT

 

394b00e5163485b7270652f6d9dabd53_1682583928_6559.png
 

 

앞의 룰이 외부에서 방화벽의 ssh 포트로의 접근을 허용한 경우라면 이번에는 방화벽이 클라이언트의 입장에서 외부의 다른 서버로 ssh 접근을 허용해 보도록 하자.

역시 그림을 그려서 생각하면 쉬울 것이다.

 

 

 

 

 

 

방화벽 클라이언트 1024: ------ 요청 --------> 22 외부 서버

1024: <----- 응답 -------- 22

 

$IPTABLES -A OUTPUT -o eth0 -p TCP --sport 1024: --dport 22 -m state --state NEW -j ACCEPT

$IPTABLES -A INPUT -i eth0 -p TCP --sport 22 --dport 1024: ! --syn -m state --state ESTABLISHED -j ACCEPT

 

방화벽에서 외부로 나가는 것이므로 OUTPUT을 먼저 생각해 보자.



‘-o eth0’eth0 인터페이스를 통해 나간다(out)는 의미이며 인터페이스가 하나일 경우에는 어차피 eth0을 통해서 나갔다 들어오므로 별도로 언급하지 않아도 된다.

 

 

 

 

그리고 방화벽이 클라이언트가 되어 외부의 22번 포트로 접속하는 경우이므로 클라이언트는 1024 이후의 임의의 포트(‘1024:’의 의미는 1024부터 65535까지의 의미와 동일하다.)가 사용되고 SYN 패킷을 달고 처음 접속하는 것이므로 상태는 NEW가 된다.

 

 

 

 

그리고 이에 대한 응답은 eth0을 통해 들어오는 패킷이므로 INPUT chain을 사용하였고 소스 포트가 22, 목적지 포트가 1024 이후의 임의의 포트가 된다.

 

 

 

 

물론 1024:라고 해서 1024 이후의 모든 포트를 허용한다는 것은 아니다.

 

 

 

 

왜냐하면 상태추적에서 ESTABLISHED라고 했으므로 초기에 접속 요청시 사용되었던 포트(이를테면 1500번 포트-어떤 포트인지는 상태추적에 의해 메모리에 남아 있다.)만을 의미하는 것이며 단지 이 포트는 수시로 변경되어 어떤 포트인지 알 수 없으므로 1024:라고 언급했을 뿐이다.

 

 

 

 

 

 

또한 SYN은 초기 접속을 요청하는 클라이언트에만 있으므로 SYN에 대한 응답 비트인 SYN/ACK 비트가 설정되어 있어 ! --syn을 설정하였다.

 

 

 

 

물론 이 설정은 하지 않아도 무방하지만 좀 더 구체적인 룰을 설정하기 위함이다.

 

 

 

 

그리고 상태추적 관점에서는 요청에 대한 응답이므로 ESTABLISHED가 된다.

 

 

 

 

물론 이미 앞에서 INPUT, OUTPUT에 대해 RELATED, ESTABLISHED는 모두 허용했으므로 두 번째 룰은 지정하지 않아도 무방하지만 완전한 룰의 이해를 위해 INPUT, OUTPUT 모두 지정하였다.

 

 

 

 

아울러 첫 번째 룰의 경우 일반적으로 OUTPUT의 기본정책은 ACCEPT이므로 별도로 언급하지 않아도 된다.

 

 

 

 

결론적으로 내부에서 외부로 나가는 접속은 모두 허용되어 있으므로 이에 대해서는 별도의 룰을 설정할 필요가 없다는 것이다.

 

 

 

 

물론 나가는 패킷도 엄격하게 정책을 설정 하였을 경우에는 OUTPUT에 대해서도 언급하여야 한다

관련자료

댓글 0
등록된 댓글이 없습니다.

공지사항


뉴스광장


  • 현재 회원수 :  60,039 명
  • 현재 강좌수 :  35,848 개
  • 현재 접속자 :  98 명