UFW는 방화벽을 명령 세 개로 설정할 수 있게 하려고 고안됐고, 그 점에서는 성공했습니다. 문제는 다른 데 있습니다. ufw status가 보여 주는 것은 결과가 아니라 의도라는 점입니다. 규칙이 목록에 있으면서도 아무것도 막지 못할 수 있습니다 — 그것도 서로 다른 세 가지 이유로, 그리고 그 셋 모두 실제 서버에서 정기적으로 발견됩니다.

스스로를 가두지 않는 시작

명령의 순서가 중요합니다. 먼저 SSH를 허용하고 그다음 켜세요.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable

SSH를 허용하기 전의 ufw enable은 당신 자신의 세션을 끊고, 그 뒤에는 업체의 콘솔만 남습니다. 서버가 이미 설정돼 있고 확신이 없다면 두 번째 연결을 열어 두세요 — 그것이 실패한 수정을 견뎌 냅니다.

자세한 상태를 보세요. 짧은 쪽은 기본 정책을 감춥니다.

sudo ufw status verbose

첫 번째 실수: 규칙은 있는데 포트는 온 세상에 열려 있다

남의 설정에서 가장 자주 보이는 한 줄:

sudo ufw allow 3306

MySQL은 이렇게 「집에서 접속할 수 있게」 열립니다 — 그리고 인터넷 전체에 열립니다. 올바른 형태는 둘이며 둘 다 이보다 낫습니다.

sudo ufw allow from 203.0.113.25 to any port 3306

또는 더 확실하게는, 서비스를 아예 밖으로 내보내지 않는 것입니다. MySQL 설정에 bind-address = 127.0.0.1, 외부 접근은 SSH 터널로. 방화벽은 두 번째 선이고, 첫 번째 선은 서비스가 공인 주소에서 대기하지 않는 것입니다. UFW의 규칙은 실수로 지워질 수 있지만 bind-address는 저절로 바뀌지 않습니다.

두 번째 실수: IPv6

ufw allow from 203.0.113.25 같은 규칙은 IPv4에만 적용됩니다. 서버에 IPv6 주소가 있다면 — 그리고 대부분의 VPS에는 있고 켜져 있습니다 — 서비스는 그것을 통해 계속 닿습니다. 업체가 주소를 줬고, 당신은 그것을 기억하지 못하며, 스캐너는 기억합니다.

v6 필터링이 켜져 있기는 한지(/etc/default/ufwIPV6=yes), 그리고 서비스가 필요 없이 ::에서 대기하고 있지는 않은지 확인하세요.

ss -tulpn | grep ':::'

주소를 명시하는 규칙은 프로토콜 버전마다 따로 써야 합니다.

세 번째 실수: Docker

가장 얄미운 것입니다. Docker는 포트를 공개할 때 자기 규칙을 UFW가 쓰는 규칙보다 앞에 iptables 체인에 넣습니다. 그 결과 -p 5432:5432로 띄운 컨테이너는 UFW가 Status: activedeny incoming 정책을 보고하는데도 인터넷에서 닿습니다. 방화벽이 망가진 것이 아니라 — 그저 차례가 오지 않는 것입니다.

치료는 UFW가 아니라 포트를 공개하는 방식에 있습니다.

ports:
  - "127.0.0.1:5432:5432"

로컬 주소에 묶는 것이 가장 단순하고 확실한 해법입니다. 밖을 향해야 하는 것은 실제로 방문자를 상대하는 것뿐입니다 — 보통은 리버스 프록시의 80과 443 포트입니다.

규칙의 순서

UFW는 처음 일치하는 규칙을 적용하고 거기서 멈춥니다. 그래서 허용 뒤에 추가한 거부는 작동하지 않습니다. 차례가 오지 않으니까요. 번호를 보고 필요한 자리에 끼워 넣으세요.

sudo ufw status numbered
sudo ufw insert 1 deny from 198.51.100.0/24
sudo ufw delete 7

규칙은 번호로 삭제하지만 삭제할 때마다 번호가 밀립니다 — 하나씩 지우고 목록을 다시 읽으세요.

외부에서의 확인

로컬 명령이 보여 주는 것은 설정된 것입니다. 실제로 어떻게 됐는지는 다른 머신에서만 보입니다.

nmap -Pn -p- 203.0.113.25
nc -zv 203.0.113.25 3306

다른 어떤 서버든 집 컴퓨터든 괜찮습니다. 이것이 거짓말하지 않는 유일한 확인이며, 눈에 띄는 재설정 뒤마다 돌려 볼 가치가 있습니다 — 특히 「네트워크를 알아서 설정하는」 무언가를 설치한 뒤에는요. Docker, 관리 패널, VPN 같은 것들.

로그

기본적으로 UFW는 거의 아무것도 쓰지 않습니다. 이것으로 켜세요.

sudo ufw logging low

기록은 /var/log/ufw.log로 갑니다 — 다만 시스템에 rsyslog가 있을 때만요. Debian 12와 Ubuntu 24.04에는 없을 수도 있고, 그때는 모든 것이 systemd의 저널로 들어갑니다.

sudo journalctl -k | grep -i '\[UFW'

비어 있는 /var/log/ufw.log는 그 자체로는 아무 의미도 없습니다 — 먼저 저널을 보세요.

방화벽에 무엇을 기대해야 하는가

UFW는 닿아서는 안 되는 것을 닫습니다. 열려 있는 것으로 오는 요청의 내용은 보지 않습니다. 443은 모두에게 열려 있고, 사이트로 오는 것은 무엇이든 막힘없이 도착합니다. 그것은 다른 도구의 몫입니다 — 애플리케이션 층의 WAF, 트래픽 층의 IDS. 방화벽의 임무는 더 소박하고 더 중요합니다. 열린 포트의 목록이 당신이 그것에 대해 믿고 있는 바와 일치하게 하는 것. 그 목록을 적용 중인 규칙과 함께 한 페이지에 두면 어떤 모습인지는 아래 데모에서.