- 워드프레스를 올려둔 NAS 웹 폴더 안에 도커 compose 파일과 데이터베이스 데이터 폴더, 설정 백업본까지 같이 두고 있었어요.
- 그 폴더는 웹 서버가 그대로 바깥에 내보내는 공간이라, 주소만 알면 밖에서 파일을 받아갈 수 있는 상태였어요.
- 민감한 파일을 웹루트 밖으로 옮기고, 직접 접근을 차단하고, 브라우저로 열어 403을 눈으로 확인하는 것까지가 한 세트였어요.
지난 08편에서는 자동화가 조용히 멈췄을 때의 이야기를 했어요. 멈춘 걸 알아채는 장치부터 만들어야 한다는 결론이었죠. 이번 09편은 그 반대쪽 이야기예요. 이번엔 아무것도 멈추지 않았어요. 스케줄도 잘 돌았고 알림도 조용했고 블로그도 멀쩡히 열렸어요. 그런데 잘 돌아가는 그 상태 그대로, 안쪽이 열려 있었어요.
어느 날 저녁에 블로그 폴더를 정리하다가 손이 멈췄어요. 워드프레스를 올려둔 NAS의 웹 폴더 안에, 도커 compose 파일과 데이터베이스 데이터 폴더, 그리고 설정 백업본이 워드프레스 파일들과 나란히 들어 있더라고요. 처음 세팅할 때 “한 폴더에 다 있으면 관리가 편하지” 하고 그렇게 둔 게 몇 달을 그대로 간 거예요.
문제는 그 폴더가 웹 서버가 바깥에 그대로 내보내는 폴더라는 점이었어요. 브라우저 주소창에 도메인을 치고 뒤에 파일 이름만 붙이면 그 파일이 그대로 내려받아지는 구조예요. 그 안에는 데이터베이스 접속 정보가 평문으로 적힌 파일도 있었고요. 누가 실제로 가져갔다는 흔적은 없었지만, 가져갈 수 있는 상태였다는 사실만으로 정리할 이유는 충분했어요.
왜 한 폴더에 전부 몰아두게 됐을까요?
돌아보면 게을러서 생긴 일이 아니라 편해서 생긴 일이었어요. 처음 도커로 워드프레스를 올릴 때는 compose 파일 하나를 어디에 두느냐가 별로 중요해 보이지 않아요. 웹 폴더에 두면 파일 탐색기에서 한 번에 다 보이고, 원격으로 접속해도 경로 하나만 기억하면 되고, 백업을 뜰 때도 그 폴더만 통째로 묶으면 되니까요.
데이터베이스 데이터 폴더도 마찬가지예요. compose 파일에서 볼륨 경로를 상대 경로로 잡으면 자연스럽게 그 옆에 생겨요. 설정 백업본도 그래요. 설정 파일을 고치기 전에 복사본을 하나 만들어 두는 건 좋은 습관인데, 그 복사본을 원본 옆에 두면 원본이 공개된 자리에서 사본까지 같이 공개되는 셈이에요.
정리하자면 나쁜 습관 세 개가 모인 게 아니라, 편한 선택 세 개가 하필 같은 폴더에서 만난 것에 가까웠어요. 그래서 몇 달 동안 눈에 안 띄었던 거고요.
웹루트에 있으면 정확히 무엇이 문제가 될까요?
웹루트는 한마디로 인터넷에 공개하기로 약속한 방이에요. 그 방 안에 있는 건 기본적으로 누구나 요청할 수 있어요. 워드프레스의 PHP 파일들은 요청이 오면 실행된 결과만 보여주니까 괜찮지만, 실행 대상이 아닌 파일은 이야기가 달라요. 텍스트 파일은 텍스트 그대로, 압축이나 덤프 파일은 파일 그대로 내려가요.
폴더 목록이 안 보인다고 파일까지 막힌 건 아니에요.이름만 알면 그대로 내려받을 수 있고, 스캐너는 그 목록을 들고 다녀요.
여기서 제가 오해하고 있던 게 하나 있었어요. 브라우저로 폴더 주소를 열었을 때 파일 목록이 안 보이길래 괜찮은 줄 알았던 거예요. 그런데 목록이 안 보이는 것과 파일을 못 받는 건 전혀 다른 이야기였어요. 목록만 가려져 있을 뿐, 이름을 아는 파일은 그대로 받아갈 수 있어요. 게다가 흔히 쓰는 이름은 굳이 알아낼 필요도 없죠. 자동으로 돌아다니는 스캐너들은 그 이름 목록을 이미 들고 다니니까요.
제가 웹 폴더에서 실제로 걷어낸 건 이런 것들이었어요.
- 컨테이너를 정의한 compose 파일 (환경변수 자리에 접속 정보가 들어가요)
- 데이터베이스가 실제 데이터를 쌓아두던 폴더
- 설정 파일을 고치기 전에 남겨둔 설정 백업본
- 예전에 한 번 떠 두고 잊어버린 데이터베이스 덤프 파일
- 편집하다 남은 임시 파일과 이름만 살짝 바꿔둔 사본
옮기고 막는 건 어떤 순서로 했을까요?
순서는 단순하게 셋으로 나눴어요. 옮기기, 막기, 확인하기예요.
먼저 옮겼어요. compose 파일과 데이터베이스 데이터 폴더, 설정 백업본을 웹루트 바깥의 별도 폴더로 통째로 옮기고, compose 안의 경로만 새 위치에 맞게 고쳤어요. 여기서 중요한 건 옮기는 게 1순위라는 점이에요. 차단 규칙은 어디까지나 보조 장치예요. 애초에 공개되는 방에 없으면, 규칙이 틀어져도 노출될 일이 없으니까요.
그다음에 막았어요. 웹 폴더에 .htaccess 규칙을 넣어서, 설정 파일이나 백업본에 흔히 붙는 확장자와 데이터 폴더로의 직접 접근을 막았어요. 대략 이런 대상들이에요.
- compose 파일에 쓰이는 .yaml 계열 확장자
- 백업본에 붙는 .bak, 그리고 .sql 같은 덤프 확장자
- 데이터베이스가 쓰던 db_data 폴더 전체
- 점으로 시작하는 숨김 파일들
규칙은 한꺼번에 넣지 않고 한 줄씩 넣으면서 블로그가 정상인지 봤어요. 차단 규칙은 잘못 쓰면 사이트 전체를 막아버리기도 하거든요. 특히 워드프레스는 자기 주소 규칙을 같은 파일에 쓰기 때문에, 그 부분은 건드리지 않고 아래쪽에 따로 붙였어요.
고쳤다고 믿지 않으려면 무엇을 확인해야 할까요?
이번 편에서 제가 가장 오래 기억하고 싶은 대목이 여기예요. 파일을 옮기고 규칙을 넣고 나면 마음이 놓여요. 그런데 그건 고친 기분이지 고쳐진 상태가 아니에요. 08편에서 자동화가 멈춘 걸 몰랐던 이유도 똑같았어요. 확인하는 절차가 없으면 사람은 자기가 한 작업을 그냥 믿어버려요.
그래서 브라우저를 열고 하나씩 직접 요청해 봤어요. 옮기기 전에 접근되던 주소들을 그대로 다시 쳐 보고, 403이나 404가 뜨는지 눈으로 봤어요. 확인할 때 챙긴 건 이 정도예요.
- 로그인 상태가 영향을 주지 않도록 시크릿 창에서 확인해요.
- 화면에 뜬 글자만 보지 말고 파일이 내려받아지는지도 봐요. 조용히 200으로 열리는 게 제일 위험해요.
- 브라우저 캐시 때문에 예전 응답이 보일 수 있으니 새로고침을 한 번 강하게 해요.
- 파일 주소뿐 아니라 폴더 주소도 따로 쳐 봐요. 파일은 막혔는데 폴더는 열리는 경우가 있어요.
- 모바일 데이터처럼 집 밖 회선으로도 한 번 열어봐요. 집 안에서만 보이는 상태와 헷갈리지 않게요.
실제로 이 단계에서 하나가 걸렸어요. 옮겼다고 생각한 설정 백업본 하나가 다른 이름으로 아직 남아 있어서 그대로 열리더라고요. 차단 규칙에 걸리는 확장자도 아니었고요. 확인을 안 했으면 정리했다고 믿은 채로 그대로 뒀을 파일이에요.
같은 실수를 안 하려면 무엇을 적어둘까요?
겁줄 이야기는 아니에요. 이런 구조는 개인 NAS에서 꽤 흔하고, 알고 나면 정리하는 데 30분이면 돼요. 대신 다음에 새 서비스를 올릴 때 같은 자리에서 또 넘어지지 않으려고 짧은 목록을 남겨뒀어요.
- compose 파일은 웹 폴더 바깥에서 시작해요. 나중에 옮기는 것보다 처음부터 밖에 두는 게 훨씬 쉬워요.
- 데이터 볼륨 경로는 상대 경로 대신 웹루트 밖의 경로로 지정해요.
- 설정 백업본은 원본 옆이 아니라 백업 전용 폴더에 둬요.
- 덤프 파일은 만든 그날 옮기거나 지워요. “나중에”는 잘 안 오더라고요.
- 차단 규칙은 넣고 끝이 아니라, 넣은 뒤 브라우저로 확인한 것만 됐다고 쳐요.
- 분기에 한 번은 웹 폴더를 눈으로 훑어요. 웹 파일이 아닌 게 섞여 있으면 그때 빼요.
08편이 “멈춘 걸 알아채는 장치”였다면 09편은 “열린 걸 알아채는 습관”이에요. 결국 둘 다 같은 말이더라고요. 내가 만든 걸 내가 다시 확인하지 않으면, 잘 돌아가는 화면은 아무것도 보증해 주지 않아요.
- compose 파일과 데이터 폴더는 웹루트 밖에 두고 시작해요.
- 설정 백업본과 덤프 파일은 원본 옆에 남기지 않아요.
- 차단 규칙은 넣은 뒤 시크릿 창에서 눈으로 확인해야 끝이에요.
같이 보면 좋은 글
다음 10편에서는 백업 이야기를 해보려고 해요. 이번에 파일을 옮기면서 백업 폴더를 열어봤는데, 백업은 성실하게 쌓여 있는데 한 번도 복구해 본 적이 없다는 것을 알게 됐거든요. 실제로 빈 폴더에 되살려 보면서 겪은 것들을 담아볼게요.