LabHub
배우기 러닝패스 코스

Network Fundamentals — Hands-on in a Linux VM

Lock Down One Server with nftables

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

이 실습은 VM 에서 돕니다

네임스페이스 srv 가 서버, cli 가 클라이언트입니다. 방화벽 규칙은 srv 안에 씁니다. VM 자신의 입력 체인을 잠그면 채점 에이전트까지 막히므로 루트 네임스페이스에는 규칙을 넣지 마세요.

목표

nftables 로 "기본은 막고 필요한 것만 연다" 를 만듭니다. 상태 추적으로 응답 패킷을 허용하고, 포트와 출처로 구멍을 내고, 버려지는 패킷을 세고, 규칙을 파일로 남깁니다.

왜 중요한가

방화벽은 규칙 목록이 아니라 순서와 기본값입니다. 기본이 drop 이면 빠뜨린 것이 막히고, accept 면 빠뜨린 것이 열립니다. 그리고 상태 추적을 모르면 "나가는 건 되는데 응답이 안 들어온다" 는 규칙을 쓰게 됩니다 — 실제로 가장 흔한 자기 잠금이 SSH 로 접속한 채 방화벽을 켜서 자기 세션의 응답까지 막는 것입니다. nftables 는 iptables 의 후속이고 쿠버네티스·도커·systemd 가 전부 이 위에서 규칙을 만들기 때문에, 읽을 줄 알아야 "누가 이 규칙을 넣었나" 를 찾습니다.

단계

  1. 네임스페이스 cli·srv 와 veth cli0srv0 를 만들어 10.70.0.2/24·10.70.0.1/24 를 붙이고 ping 이 되게 하세요.
  2. srv10.70.0.1:80 을 듣는 python3 -m http.server10.70.0.1:2222 를 듣는 nc -lk 를 띄우세요.
  3. srv 에 테이블 inet fwinput 훅 체인(정책 drop)을 만들어 cli 에서 아무것도 안 되게 하세요.
  4. input 체인에 lo 허용, ct state established,related 허용, icmp 허용 세 규칙을 넣어 ping 이 다시 되게 하세요.
  5. tcp dport 80 허용 규칙을 넣어 cli 에서 웹은 되고 2222 는 여전히 안 되게 하세요.
  6. ip saddr 10.70.0.2 에서 오는 tcp dport 2222 만 허용하는 규칙을 넣으세요.
  7. 체인 끝에 counter drop 규칙을 두고 cli 에서 3333 포트를 두드린 뒤, 그 카운터가 보이는 nft list chain 출력을 /root/fw/dropped.txt 에 저장하세요.
  8. srv 의 전체 규칙을 /root/fw/ruleset.nft 에 저장하세요. nft -c -f 로 문법이 통과해야 합니다.

참고

서버와 클라이언트

네임스페이스 cli·srv 와 veth cli0srv0 를 만들어 10.70.0.2/24·10.70.0.1/24 를 붙이고 ping 이 되게 하세요.

cli0cli 에 10.70.0.2, srv0srv 에 10.70.0.1. lo 까지 UP. ip netns exec cli ping -c 1 10.70.0.1.

서비스 둘

srv10.70.0.1:80 을 듣는 python3 -m http.server10.70.0.1:2222 를 듣는 nc -lk 를 띄우세요.

둘 다 ip netns exec srv setsid … > 로그 2>&1 < /dev/null & 로. ip netns exec srv ss -ltn 에 80 과 2222 가 LISTEN 이어야 하고, ip netns exec cli curl -s http://10.70.0.1/ 이 무언가를 돌려줘야 합니다.

기본은 막는다

srv 에 테이블 inet fwinput 훅 체인(정책 drop)을 만들어 cli 에서 아무것도 안 되게 하세요.

nft add table inet fwnft 'add chain inet fw input { type filter hook input priority 0; policy drop; }'. 이제 cli 의 ping 도 curl 도 응답 없이 시간 초과여야 합니다(refused 가 아니라).

기본 세 줄

input 체인에 lo 허용, ct state established,related 허용, icmp 허용 세 규칙을 넣어 ping 이 다시 되게 하세요.

nft add rule inet fw input iifname "lo" accept, … ct state established,related accept, … ip protocol icmp accept 셋. 이 셋은 거의 모든 방화벽의 첫 줄입니다.

80 만 연다

tcp dport 80 허용 규칙을 넣어 cli 에서 웹은 되고 2222 는 여전히 안 되게 하세요.

nft add rule inet fw input tcp dport 80 accept. 확인: curl -s -m 2 http://10.70.0.1/ 은 되고, nc -z -w 2 10.70.0.1 2222 는 실패해야 합니다.

출처로 좁힌다

ip saddr 10.70.0.2 에서 오는 tcp dport 2222 만 허용하는 규칙을 넣으세요.

nft add rule inet fw input ip saddr 10.70.0.2 tcp dport 2222 accept. 포트를 열되 특정 출처에만 — 관리 포트는 이렇게 좁힙니다. ip netns exec cli nc -z -w 2 10.70.0.1 2222 가 되어야 합니다.

버려지는 것을 센다

체인 끝에 counter drop 규칙을 두고 cli 에서 3333 포트를 두드린 뒤, 그 카운터가 보이는 nft list chain 출력을 /root/fw/dropped.txt 에 저장하세요.

nft add rule inet fw input counter dropip netns exec cli nc -z -w 1 10.70.0.1 3333 을 한두 번. ip netns exec srv nft list chain inet fw input > /root/fw/dropped.txtcounter packets N 이 0 보다 커야 합니다. netns 안에서 log 를 쓰려면 net.netfilter.nf_log_all_netns=1 이 필요하다는 것도 알아 두세요.

규칙을 파일로

srv 의 전체 규칙을 /root/fw/ruleset.nft 에 저장하세요. nft -c -f 로 문법이 통과해야 합니다.

ip netns exec srv nft list ruleset > /root/fw/ruleset.nft. 실제 서버라면 이 파일이 /etc/nftables.conf 가 되어 부팅 때 nft -f 로 읽힙니다. nft -c -f /root/fw/ruleset.nft 가 아무 말 없이 끝나면 통과입니다.