모든 시스템 정상 작동 14개 리전 · 1.2 TBPS 방어 충전 수단 BTC · XMR · LTC · ETH · USDT +3 코인

튜토리얼

새 VPS를 하드닝하는 방법: 첫 10분이 전부다

11분 읽기

새 VPS를 하드닝하는 방법: 첫 10분이 전부다

새 서버는 IP 주소를 받는 그 순간 가장 크게 노출된다. 자동화된 스캐너는 IPv4 전체 공간을 쉬지 않고 훑고 다니므로, 1분 전에 배포한 박스에 대한 첫 로그인 시도는 대개 환영 메시지를 다 읽기도 전에 도착한다. 이는 당신을 노린 공격이 아니다 — 배경 방사선 같은 것이며, root에 비밀번호를 걸어 둔 하드닝되지 않은 서버가 몇 달이 아니라 몇 시간 단위로 뚫리는 이유이기도 하다. 다행히 이를 막는 일은 짧게 끝난다: 정해진 순서로 10분만 들이면 기회주의적 위험은 사실상 모두 사라진다. 이 가이드는 그 체크리스트와, 스스로를 걸어 잠그지 않는 순서, 그리고 대부분의 하드닝 튜토리얼이 절대 언급하지 않는 한 가지 — 당신과 연결되지 않게 하려고 일부러 빌린 머신에 기본 설정이 조용히 남겨 놓는 개인정보까지 다룬다.

하드닝이 실제로 지켜주는 것

하드닝을 할 가치가 있는 이유는 정확히, 그 효과가 좁지만 확실하기 때문이다. 그 경계를 분명히 알아 두어야 하드닝이 닿지 않는 영역에서 잘못된 안전감에 빠지지 않는다.

  • 기회주의적 공격자를 완전히 차단한다. 크리덴셜 스터핑 봇, SSH 무차별 대입, 노출된 관리자 패널을 노리는 스캔 모두 키 전용 인증과 기본 거부 방화벽 앞에서는 실패한다.
  • 당신이 돌리는 무언가에 결함이 있을 때 피해 범위를 제한한다. 닫힌 포트 뒤에서 localhost에만 바인딩된 서비스는 그 CVE가 공개되는 날에도 낯선 사람이 닿을 수 없다.
  • 실수 하나의 대가를 줄여준다. 권한 없는 사용자, 분리된 키, 자동 패치가 있으면 잘못된 판단 하나로 머신 전체를 내주는 일은 없다.
  • 서버를 호스트로부터 숨겨주지는 않는다. 하이퍼바이저에 접근할 수 있는 사람은 원칙적으로 가동 중인 머신의 메모리를 읽을 수 있다 — 이는 방화벽 규칙이 아니라 누구에게서 빌리는가의 문제다.
  • 당신을 익명으로 만들어주지도 않는다. 하드닝은 박스를 지켜줄 뿐이다. 그 박스가 당신의 이름과 연결되는지는 첫 로그인보다 훨씬 전, 가입과 결제 시점에 이미 정해진다.

사람들이 가장 자주 거꾸로 이해하는 것이 바로 이 마지막 구분이다. 본명으로 신용카드를 긁어 완벽하게 하드닝한 서버라 해도, 여전히 당신의 본명으로 된 서버일 뿐이다. 이 두 계층은 서로 보완적이다: no-KYC 호스팅과 암호화폐로 채운 잔액이 서류상 그 머신이 누구의 것인지를 결정하고, 아래에 나오는 10분이 그 안에 누가 들어갈 수 있는지를 결정한다.

스스로를 걸어 잠그지 않는 순서

하드닝에 얽힌 공포담은 거의 다 같은 이야기다: 키가 작동하는지 확인하기도 전에 비밀번호 인증부터 꺼버렸거나, SSH 규칙이 빠진 방화벽을 켜버려서 더 이상 닿을 수 없는 머신 밖으로 스스로를 걸어 잠근 것이다. 순서가 존재하는 이유는 바로 이런 일을 원천적으로 막기 위해서다. 키를 먼저 설치하고 두 번째 창에서 작동을 확인하라. 그런 다음에야 비밀번호를 끈다. 방화벽 규칙에 SSH를 추가하는 것은 반드시 방화벽을 켜기 전이어야 하며, 절대 나중이 되어서는 안 된다.

sshd_config나 방화벽 규칙을 편집하는 동안에는 첫 번째 SSH 세션을 계속 열어 둔 채로 유지하고, 모든 변경 사항을 두 번째 터미널에서 테스트하라. 열려 있는 세션은 잘못된 설정에서도 살아남는다 — 그것이 바로 돌아올 수 있는 통로다. 두 번째 창이 연결되면 그 변경은 안전했던 것이고, 연결되지 않으면 첫 번째 세션에서 바로잡으면 된다.

복구 경로가 무엇인지 필요해지기 전에 미리 알아두는 것도 가치가 있다. SSH로만 접근할 수 있는 VPS에는 문이 정확히 하나뿐이므로, 제공업체 대시보드의 콘솔이야말로 잠금을 재구축이 아니라 사소한 불편으로 바꿔주는 대안이다. 아직 모든 것이 멀쩡할 때 그 콘솔을 열 수 있는지 미리 확인해 두어라.

단계별 안내: 새 박스에서 보내는 첫 10분

  1. 01패키지 인덱스와 설치된 패키지 업데이트하기새 이미지는 빌드된 시점의 스냅샷일 뿐이다. 최신 상태로 맞추는 것이 목록에서 가장 값어치가 큰 작업이며, 1분도 채 걸리지 않는다.
  2. 02sudo 권한을 가진 일반 사용자 만들기항상 root로 작업한다는 것은 오타 하나, 프로세스 하나까지 전권을 쥔 채 실행된다는 뜻이다. 일반 사용자를 만들어 sudo나 wheel 그룹에 추가하고, 그 계정을 사용하라.
  3. 03그 사용자에게 공개 키 복사하기아직 없다면 자신의 머신에서 ed25519 키를 생성한 다음, ssh-copy-id로 공개 키 절반만 전송하라. 개인 키는 절대 노트북을 벗어나지 않는다.
  4. 04두 번째 터미널을 열고 키 로그인이 되는지 확인하기이 단계를 건너뛰지 마라. 인증과 관련된 무언가를 바꾸기 전에, 새 창에서 키로 새 사용자로 로그인해 보라.
  5. 05비밀번호 인증과 root 로그인 비활성화하기PasswordAuthentication no와 PermitRootLogin prohibit-password를 설정한 다음 sshd를 다시 불러오라. 이제 박스를 노린 무차별 대입 공격은 더 이상 추측할 대상이 없다.
  6. 06SSH만 허용한 기본 거부 방화벽 활성화하기모든 인바운드를 거부하고, SSH 포트만 허용한 다음 활성화하라. 자신의 서비스에 필요한 포트는 그 이후에 하나씩 추가하면 된다.
  7. 07자동 보안 업데이트 켜기Debian과 Ubuntu에서는 unattended-upgrades, RHEL 계열에서는 dnf-automatic을 사용하라. 6개월 뒤 더 이상 신경 쓰지 않게 되었을 때도 머신을 안전하게 지켜주는 것이 바로 이것이다.
  8. 08무엇이 열려 있는지 확인하고 있어서는 안 될 것은 닫기ss -tulpn 한 번이면 열려 있는 모든 소켓을 확인할 수 있다. 의도적으로 열어두지 않은 것은 모두 제거하거나 localhost에 바인딩해야 한다.

SSH: 키만 남기고, 중요한 설정들

공개 키 인증이 SSH 하드닝의 전부라고 해도 과언이 아니다. 비밀번호를 끄고 나면 공격자에게는 갖고 있지 않은 개인 키가 필요해지며, 아무리 추측해도 그 키는 나오지 않는다. ed25519 키를 생성하라 — 짧고 빠르며 요즘의 기본값이다 — 그리고 키에 패스프레이즈를 걸어서 노트북을 도난당해도 서버까지 도난당하지 않게 하라. sshd_config의 나머지 설정은 모두 이 한 가지 결정 위에 얹히는 다듬기에 불과하다.

  • PasswordAuthentication no — 무차별 대입을 끝내는 설정이다. 먼저 두 번째 세션에서 키가 작동하는지 확인하라.
  • PermitRootLogin prohibit-password — 복구용으로 키를 통한 root 접근은 여전히 가능하지만, 비밀번호로는 절대 불가능하다. sudo 사용자가 제대로 동작함을 확인했다면 no로 바꿔라.
  • AllowUsers 또는 AllowGroups — 애초에 누가 로그인할 수 있는지 명시적으로 허용 목록을 두어, 어떤 패키지가 만든 서비스 계정이 SSH 진입점이 되는 일을 원천 차단한다.
  • KbdInteractiveAuthentication no — 일부 배포판에서 조용히 비밀번호 프롬프트를 다시 열어버릴 수 있는 또 다른 대화형 경로를 닫는다.
  • 개인 키 하나를 여기저기 복사해 쓰지 말고, 기기마다 별도의 키를 써라. 휴대폰을 잃어버렸을 때는 authorized_keys에서 한 줄만 지우면 되어야지, 모든 것을 다시 발급해야 해서는 안 된다.
  • SSH를 22번 포트 밖으로 옮기면 로그량이 극적으로 줄어들지만, 이는 보안이 아니라 소음 감소로 취급해야 한다 — 실제로 당신의 IP를 들여다보는 사람에게는 아무것도 달라지지 않는다.

키보다 한 걸음 더 나아가고 싶다면, 가장 강력한 방법은 SSH를 아예 공개하지 않는 것이다: 머신을 WireGuard 터널 뒤에 두고, 22번 포트를 방화벽으로 막아 터널 주소에서 오는 연결만 받아들이게 하라. 그러면 SSH 데몬은 인터넷이 아예 볼 수 없는 존재가 되며, 이는 노출된 상태에서 아무리 설정을 다듬는 것보다도 나은 결과다.

방화벽: 기본은 거부, 쓰는 것만 정확히 연다

방화벽은 기본값이 거부일 때만 의미가 있다. 일단 다 허용해 놓고 알려진 나쁜 포트만 막는 방식은 순서가 거꾸로다 — 결국 기억하고 있던 서비스만 지키고, 잊어버린 서비스는 그대로 노출된다. 모든 인바운드 트래픽을 거부하고 아웃바운드는 허용한 다음, 필요한 것을 배포할 때마다 포트를 하나씩 열어라. 요즘 리눅스는 내부적으로 nftables를 쓰며, ufw나 firewalld는 그 위에 얹히는 훌륭한 프런트엔드다 — 어떤 도구를 쓰는지보다 기본값이 무엇인지가 훨씬 더 중요하다.

  • 방화벽을 켜기 전에 SSH부터 허용하라, 나중이 아니라. 이것이 스스로를 걸어 잠그는 두 번째로 흔한 방법이다.
  • 서비스가 외부로부터 정말로 필요로 하는 포트만 열어라. 웹 서버라면 80과 443이 필요하지만, 데이터베이스는 거의 아무것도 필요하지 않다.
  • 로컬 전용 서비스는 0.0.0.0이 아니라 127.0.0.1에 바인딩하라. 닫힌 포트와 애초에 공개적으로 리스닝하지 않는 서비스는 서로 독립된 두 겹의 방어이며, 둘 다 갖추어야 한다.
  • IPv4뿐 아니라 IPv6 규칙도 작성하라. 듀얼 스택 박스에서 v4만 다루는 규칙 세트는 같은 서비스를 v6 주소에서 활짝 열어둔 채로 방치하는 셈이다.
  • 가능하다면 관리용 포트는 출발지 주소로 제한하라. 관리 접속이 항상 하나의 VPN 엔드포인트에서 온다면, 그 사실을 규칙에 명시하라.
  • 서비스를 추가한 뒤에는 규칙을 다시 읽어보라. 이미 지워버린 무언가를 위해 열어두었던 포트야말로 깔끔했던 시작을 조용히 무너뜨리는 것들이다.

일부 워크로드는 이 논리를 뒤집어 일부러 활짝 열린 포트를 필요로 한다 — Tor 릴레이는 어디서든 오는 연결을 받아들여야 하고, Bitcoin 풀 노드는 8333에 닿을 수 있어야만 피어에게 서비스를 제공한다. 그것도 괜찮다. 원칙은 "아무것도 열지 마라"가 아니라 "의도적으로 열어라"이며, 공개되도록 설계된 서비스라면 그 자체가 의도적인 선택이다.

fail2ban, 그리고 생각보다 덜 중요한 이유

fail2ban은 로그를 지켜보다가 인증에 반복해서 실패하는 주소를 차단한다. 분명 유용하지만, 이미 비밀번호 인증을 꺼버린 뒤라면 그것이 실제로 무엇을 해주는지 솔직해질 필요가 있다: 그 시점부터는 아무도 추측만으로 성공할 수 없으므로, fail2ban이 더 이상 침입을 막아주는 것은 아니다. 대신 막아주는 것은 하루 수천 줄에 이르는 쓸모없는 로그, 그 접속 시도들이 잡아먹는 CPU, 그리고 몇 달 전부터 더 이상 읽지도 않는 소음 속에 진짜 사건이 묻혀버릴 위험이다.

그래도 10초짜리 설정을 해 둘 가치는 충분하며, 비밀번호를 실제로 받는 무언가 — 웹 애플리케이션 로그인, 메일 서버, 컨트롤 패널 — 를 돌리는 순간 진짜로 보호 효과를 발휘한다. sshd만이 아니라 그런 로그들도 가리키게 설정하라. 차단 기간은 분이 아니라 시간 단위로 설정하고, 손가락이 미끄러진 비밀번호 한 번으로 자기 머신에서 스스로 차단당하지 않도록 자신의 주소는 무시 목록에 추가해 두어라.

fail2ban이 비밀번호 인증을 계속 켜 두는 핑계가 되게 하지 마라. 이것은 속도 제한 장치일 뿐, 인증 수단이 아니다. 인터넷의 추측 게임 자체에서 완전히 발을 빼게 해주는 것은 키이며, fail2ban은 그 이후 로그를 읽을 수 있는 상태로만 유지해 줄 뿐이다.

기억하지 않아도 되는 업데이트

제대로 설정된 서버가 실제로 마주하는 위협은 누군가 SSH 키를 뚫어내는 것이 아니다. 설치해 놓고 잊어버린 무언가에 대해 취약점이 공개되고, 사흘 뒤 다른 일을 하는 사이 스캐너에게 이용당하는 것이다. 자동 보안 업데이트가 그 답이며, Debian이나 Ubuntu에서는 보안 패키지만 설치하도록 설정한 unattended-upgrades가, Fedora나 Rocky, Alma에서는 dnf-automatic이 그 역할을 한다. 첫 10분 사이에 이를 켜두면, 당신의 관심이 다른 곳으로 옮겨간 한참 뒤에도 머신은 스스로 패치를 계속한다.

커널과 libc 업데이트만은 여전히 당신의 손이 필요한 예외다: 재시작을 거쳐야만 적용되므로, 400일째 켜져 있는 서버는 거의 확실히 1년 전에 디스크에서나 패치된 코드를 그대로 돌리고 있는 셈이다. Debian의 needrestart는 어떤 서비스가 이미 지워진 라이브러리를 붙든 채 돌아가고 있는지 알려주며, 한 달에 한 번이라도 정해진 재부팅 창을 두는 것이 설치된 패치와 실제로 적용된 패치 사이의 차이를 만든다. 어차피 무엇을 돌리든 예기치 못한 재부팅쯤은 견뎌내야 한다 — 그렇지 못하다면 그것은 따로 고쳐야 할 별개의 문제다.

하드닝 체크리스트가 놓치는 신원 유출

오프쇼어, no-KYC 호스트를 일부러 선택했다면 이 절이 특히 중요하다. 일반적인 하드닝 가이드는 소유자가 공개 기록에 남아 있는 회사 서버를 염두에 두고 쓰여지므로, 기본 설정이 당신에 대해 무엇을 기록해 두는지는 애초에 묻지 않는다. 익명으로 빌린 머신에서는 그런 기본값 몇 가지가 조용히 당신의 이름을 다시 그 위에 붙여 놓는다.

  • SSH 공개 키에는 주석이 붙는다 — 기본값으로는 당신의 로컬 사용자 이름과 노트북 호스트네임, 이를테면 alex@alex-macbook 같은 형태이며 — 이 주석은 서버의 authorized_keys에 그대로 저장된다. 키를 생성할 때 -C 플래그로 직접 지정하거나, 복사한 뒤 그 줄을 편집하라.
  • 당신이 정한 서버 호스트네임은 로그, 메일 헤더, 모니터링 출력, 때로는 서비스 배너에까지 그대로 남는다. 평범한 호스트네임은 아무것도 드러내지 않지만, 당신이나 회사의 이름이 들어간 호스트네임은 그렇지 않다.
  • 시스템 타임존이다. 클라우드 이미지는 기본값이 UTC이며, 이는 아무에게도 아무것도 알려주지 않는다. 이를 자신의 로컬 시간대로 바꾸는 순간 당신이 어디에 있는지가 좁혀지고, 이후 모든 로그의 타임스탬프가 당신의 활동 시간대를 확인해 준다.
  • 박스에 복사해 넣은 Git 설정에는 당신이 커밋할 때 쓰는 이름과 이메일 주소가 담겨 있다. 셸 히스토리 파일, 워크스테이션에서 동기화한 닷파일, 급하게 테스트하다 캐시된 자격 증명도 마찬가지다.
  • 인증서를 발급받을 때 Let's Encrypt에 건네는 이메일 주소는 그 인증서의 공개 기록 일부가 된다. 당신의 신원과 연결되지 않은 주소를 사용하라.
  • 웹 서버 버전 배너와 X-Powered-By 헤더, 그리고 계정 식별자를 매단 채 머신에서 자기 회사로 신호를 보내는 분석 도구, 크래시 리포터, 벤더 모니터링 에이전트도 마찬가지다.
유용한 습관은 대여한 서버를 클린룸처럼 다루는 것이다. 개인적인 것은 아무것도 그 위에 복사해 넣지 않는다 — 닷파일 저장소도, 동기화된 셸 히스토리도, 노트북 이름이 담긴 주석이 붙은 키도 안 된다. 애초에 기록되지 않은 것은 디스크 이미지에서 복구될 수 없고, 당신 다음에 그 박스를 들여다보는 누구에게도 발견되지 않는다.

이 계층들을 헷갈리지 않고 구분해 두는 것이 중요하다. 하드닝은 낯선 사람을 머신 밖으로 막아준다. 이런 세부 사항들은 이미 그 머신을 들여다보고 있는 누군가에게 머신이 당신에 대해 떠벌리지 못하게 막아준다. 그리고 결제 계층은 애초에 찾아낼 이름이 존재했는지 자체를 결정한다 — 이 주제는 Bitcoin으로 VPS를 사면 정말 익명인가에서 솔직하게 다루었고, Monero로 충전하는 것은 그보다 한 걸음 더 나아간다. 각 계층은 홀로는 무너지지만, 함께라면 버텨낸다.

백업: 하드닝이 대신해 줄 수 없는 부분

어떤 방화벽 규칙도 삭제된 데이터베이스나 고장 난 디스크, 그때는 합리적으로 보였던 설정 변경으로부터는 지켜주지 못한다. 백업은 스스로 저지른 실수로부터 당신을 구해주는 유일한 대책이며, 통계적으로 잘 보안된 머신에서 데이터를 잃는 가장 유력한 경로가 바로 그것이다. 서버를 벗어나기 전에 암호화하고, 최소 한 벌은 서버 자체가 닿을 수 없는 곳에 보관하며, 기억날 때가 아니라 정해진 일정에 맞춰 실행되게 하라.

마지막 항목은 들리는 것보다 훨씬 중요하다: 서버가 덮어쓸 수 있는 백업 프로세스는 그 서버에서 root 권한을 가진 무엇이든 파괴할 수 있는 백업이기도 하다. 암호화한 아카이브를 별도의 스토리지 서버로 밀어 넣거나 — 혹은 자격 증명이 백업 대상 머신 밖에 머물도록 그쪽에서 끌어오는 방식으로 — 머신이 사라져도 살아남는 사본을 확보하라. 그리고 아무 문제도 없을 때 일부러 한 번쯤 복원을 직접 해보라. 테스트해보지 않은 백업은 안전망이 아니라 그저 가설일 뿐이다.

조용히 공든 탑을 무너뜨리는 실수들

  • 키를 테스트하기도 전에 비밀번호 인증부터 꺼버린 다음, 더 이상 로그인할 수 없는 노트북 앞에서야 실수를 깨닫는 경우.
  • SSH를 허용하기 전에 방화벽부터 켜버리는 경우 — 반대 방향에서 도달한 같은 잠금이다.
  • IPv4 규칙만 작성하고, 박스의 IPv6 주소에서는 모든 서비스가 그대로 닿을 수 있게 방치하는 경우.
  • 첫날에는 꼼꼼히 하드닝해 놓고, 이후 컨트롤 패널과 데이터베이스, 모니터링 스택을 설치하면서 저마다 묻지도 않고 자기 포트를 열어버리는 경우.
  • sudo 한 번 덜 치려고 모든 것을 root로 돌리는 경우 — 그중 무엇 하나에서라도 결함이 나오면 곧바로 전체가 뚫린다.
  • fail2ban을 키의 대체품으로 여기는 경우 — 그저 속도만 느려졌을 뿐인 비밀번호 추측 게임을 계속 돌아가게 내버려 두는 셈이다.
  • 디스크를 암호화하면 대여한 서버를 호스트로부터도 감출 수 있다고 착각하는 경우 — 전체 디스크 암호화는 도난당한 드라이브를 지켜줄 뿐, 가동 중인 머신은 지켜주지 못한다.
  • 재부팅을 아예 하지 않는 경우 — 몇 달치 커널 패치가 디스크에 설치된 채 쌓여 있는 동안 예전 커널이 계속 돌아간다.

이 중 어느 것도 어렵지 않고, 오래 걸리지도 않는다. 순서대로 진행하고, 다음 단계로 넘어가기 전에 매번 두 번째 터미널에서 확인하면, 몇 분 전에 배포한 그 머신은 더 이상 주소 공간을 훑는 누구에게나 열린 기회가 아니게 된다. 그런 다음에야 애초에 하려던 것 — 웹사이트든, 노드든, 터널이든, 프라이빗 모델 엔드포인트든 — 을 이제는 근거를 갖고 이해할 수 있는 토대 위에서 배포하라.

지금 시작해 볼까요?오프쇼어 VPS를 최저 $3.99/월부터 배포 — KYC 없음, 암호화폐로 결제. 시작하기