서버 보안용 대시보드 제작기
회사 서버용으로 만들어둔게 하나 있는데, 외부 접근 시도를 모아서 보여주는 대시보드인데 집 서버에도 있으면 좋겠다 싶어서 옮겨왔다.
우분투 기본 auth.log는 4주 지나면 없어지기 때문에 나중에 "언제부터 이랬지?"를 확인하기 위한 아이디어
구조
로그 읽어서 SQLite에 넣고 웹으로 보여주는게 전부
sshd / fail2ban → /var/log (읽기전용 마운트) ┐
traefik access.log → ~/proxy/logs (읽기전용) ├→ 수집기 → SQLite → FastAPI
┘ ↑ traefik ← authentik
포트오픈 X traefik 뒤에 authentik SSO 붙여놨고 랜이랑 vpn에서만 닿는다.
수집요소는 다음과 같다
sshd-> 로그인 성공/실패 (journald에서)fail2ban-> 차단/해제traefik-> 웹 접근이랑 수상한 경로 스캔
이벤트마다 dedup_key를 박아둔게 나중에 중요해진다. 로그 파일이 회전되면 수집기가 처음부터 다시 읽는데, 키가 있으니까 겹쳐 읽어도 중복이 안 쌓임
회사 버전과 차이
회사 서버에서는 자체 메일도 쓰느라고 mailcow가 있어서 메일 로그도 보고 메일 차단도 걸 수 있는데 집 서버엔 mailcow가 없다(수발신은 gmail 로 대신함) 그래서 차단 목록 화면에 계속 이런게 떴다.
REDIS_URL 미설정 - mailcow 차단 상태를 읽을 수 없습니다
경고만 뜨는게 아니라 목록 자체가 안 나와서 차단이고 뭐고 아무것도 못함. 아예 코드를 지울까 하다가 나중에 메일카우 쓸 수도 있어서 걍 분기처리 햇다.
MAIL_ENABLED: bool = bool(CONFIG["redis_url"])
이 대시보드가 못하는 것
차단 버튼이 달려있긴 한데 웹만 막는다. traefik에 ban-<ip>.yml 써서 그 IP 요청을 전 도메인에서 403 주는 방식으로..
ssh는 root 권한이 필요한데 감시 도구한테 네트워크 제어 권한까지 주는건 좀 그래서 원본 만들때부터 뺐다. ssh는 어차피 fail2ban이 잘 막아준다(고 믿는다) 그래서 "지금 차단 중" 목록에 fail2ban이 막고있는 IP는 안 나온다.
logrotate가 몰래 놀고 있었던 건
스택을 /home/hyunie로 옮기고 나서 logrotate 설정이 옛날 경로를 가리키고 있었다. 그 파일은 이제 없는데, logrotate는 파일이 없으면 오류도 안내고 그냥 넘어간다.
즉 access.log가 몇 달째 회전 안되고 계속 쌓이는 중이었다. 경로 고치고 강제로 한번 돌려서 확인했다.
220KB -> access.log.1 로 이동 / 본체 0바이트 / inode 유지
요청 3건 후 : 겉보기 2694B / 디스크 8블록 / 널바이트 0
traefik fd pos=2694 -> 파일 크기랑 일치
secwatch 커서도 알아서 0으로 돌아갔다가 따라옴
copytruncate 쓰는게 안전한 이유도 실측해뒀다. traefik이 access.log를 O_APPEND로 열어서 파일을 잘라도 다음 쓰기가 0부터 나간다. 안 그러면 앞부분이 널로 채워진 sparse 파일이 생긴다.
마치며
설정 파일이 있다고 동작하는게 아니다.