VPS 보안 기초: 방화벽과 포트 관리

UFW 설정, SSH 포트 변경, Cloudflare Tunnel을 활용한 서버 보안 구성기

@@@@@@@@@@%%%%%%%%%%%@@@@@@@@%%@@@@@@@@@@
@@@@@@@%%%%#****************#@@%%@@@@@@@
@@@@%%%%#+:         .........-+%@@%@@@@@
@@%%%#+:  .-========*******+=:..-*%%%@@@
@@%%%*  :===========**********+-  *@%@@@
@@%%%*  ============***********+..*@%@@@
@@%%%*  ============****=.:+***+..*@%@@@
@@%%%*  ============**=: :=+***+..*@%@@@
@@%%%*  =====:.-=====: .=******+..*@%@@@
@@%%%*  =====:  .--. .=********+..*@%@@@
@@%%%#. :======:    =**********- :%%%@@@
@@@%%%+  -=======-:=**********=..*@%%@@@
@@@@%%%+  :=========*********- .*@%%@@@@
@@@@@%%%*: .-=======*******+: -#@%%@@@@@
@@@@@@%%%%+. .-=====*****=: :+%@%@@@@@@@
@@@@@@@@%%%#+.  :===**+-. :+%@%%@@@@@@@@
@@@@@@@@@@%%%%*-   :-:..-*%@%%@@@@@@@@@@
@@@@@@@@@@@@%%%%#+-..=*%@@%@@@@@@@@@@@@@
@@@@@@@@@@@@@@@%%%%%%@@%@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@%%%@@@@@@@@@@@@@@@@@@@

TL;DR

  • 방화벽(UFW) 없이 서버 운영하고 있었다 — 위험
  • 외부에 Dokploy(3000), WordPress(8080/8081), Docker Swarm(2377/7946) 노출 상태
  • wp-login.php 브루트포스 공격이 IP 직접 접근으로 들어오고 있었음
  • UFW 켜서 SSH(22)만 허용, 나머지 전부 차단
  • Cloudflare Tunnel 경유 서비스는 영향 없음 (localhost 통신)

오늘 배운 것

VPS 서버의 기본 보안을 설정했다. 방화벽 없이 운영되고 있던 서버에 UFW를 적용하고, 불필요한 포트를 차단했다.

현재 상태 파악

1
ss -tlnp | grep -v '127.0.0'

외부에 노출된 포트를 확인하니 SSH(22), sslh(443) 외에도 Dokploy(3000), WordPress(8080, 8081), Docker Swarm(2377, 7946)이 열려 있었다.

포트    서비스           필요    위험도
──────────────────────────────────────
22      SSH              O      브루트포스 (fail2ban 있음)
443     sslh → SSH       O      회사 우회용
3000    Dokploy          X      관리패널 노출
8080    WP 한국어        X      직접 노출 불필요
8081    WP 영어          X      직접 노출 불필요
2377    Docker Swarm     X      클러스터 관리 포트
7946    Docker Swarm     X      노드 통신 포트

WordPress 로그를 확인하니 외부 IP에서 직접 wp-login.php를 때리고 있었다.

161.35.157.115 - POST /wp-login.php  ← 반복 브루트포스
159.223.228.106 - POST /wp-login.php ← 반복 브루트포스

UFW 설정

1
2
3
4
5
6
7
8
# 필요한 포트만 허용
sudo ufw allow 22/tcp

# 방화벽 활성화
sudo ufw --force enable

# 확인
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)

Cloudflare Tunnel과의 관계

Cloudflare Tunnel을 사용하면 웹 서비스는 터널 경유로 접근한다. 터널 데몬(cloudflared)이 localhost에서 각 서비스로 연결하므로 외부 포트를 열 필요가 없다.

[사용자] → Cloudflare Edge → Tunnel → localhost:3000 (Dokploy)
                                    → localhost:8080 (WP KO)
                                    → localhost:8081 (WP EN)

UFW가 차단하는 건 IP 직접 접근뿐이다. 도메인 경유 접근은 터널을 타므로 영향 없음.

SSH 포트 변경

기존에 sslh를 통해 443 포트로 SSH를 우회하는 구조였는데, Cloudflare Tunnel로 SSH 접속이 가능해지면서 표준 포트(22)로 변경했다.

1
2
3
# /etc/ssh/sshd_config
Port 22
PermitRootLogin prohibit-password

Wrap Up

방화벽 설정은 서버 운영의 가장 기본적인 보안 조치다. 하지만 오늘 실제로 경험해보니, “기본"이라는 말이 “쉽다"는 뜻은 아니었다.

UFW를 켜기 전에 열린 포트를 확인했을 때, Docker Swarm 관리 포트(2377, 7946)까지 외부에 노출되어 있었다. Docker가 자체적으로 iptables 규칙을 추가하기 때문에, UFW만으로는 Docker 컨테이너의 포트 노출을 완전히 제어할 수 없다. 이 부분은 별도로 다뤄야 할 주제다.

한 가지 더 생각해볼 것: Cloudflare Tunnel을 사용하면 사실상 외부에 포트를 열 필요가 없어진다. 그렇다면 SSH(22)마저도 터널로 대체하고 모든 포트를 닫아버리는 것이 궁극적인 방향일까? 포트가 하나도 열려있지 않은 서버 — 매력적이지만, 터널 서비스 자체에 장애가 나면 접근 방법이 사라진다는 리스크도 함께 안게 된다.

보안은 결국 편의와 안전 사이의 트레이드오프다. 중요한 건 그 균형점을 의식적으로 선택하는 것이다.

다른 사람들은 이 균형을 어디에 두고 있을까. SSH 포트는 22번 그대로 쓰는 걸까, 바꾸는 걸까. 터널만 믿고 포트를 다 닫아버린 사람도 있을까.

Built with Hugo
Theme Stack designed by Jimmy