침입 방지
fail2ban 방식의 침입 방지입니다. 로그에서 무차별 대입 공격을 찾고, 사용하지 않는 포트에 미끼를 두고, 포트 스캔을 집계해 악성 IP를 차단 목록에 추가하며, 이를 시스템 방화벽(nftables)에 동기화해 커널에서 해당 IP의 모든 트래픽을 버립니다.
기능
- 로그 규칙: 로그 파일, systemd 저널, 명령 출력(OpenWrt의
logread -f등), Docker 컨테이너 로그를 읽어 정규식으로 실패 기록을 찾고, 집계 기간 내에 횟수에 도달한 IP를 차단합니다. SSH, Dropbear, Nginx, Vaultwarden, Home Assistant, Proxmox VE 등의 템플릿이 들어 있으며, 규칙을 편집할 때 로그 샘플을 붙여 넣어 바로 테스트할 수 있습니다. - Gately 이벤트: 관리 콘솔 로그인 실패와 WAF 차단도 규칙의 출처로 쓸 수 있으며 정규식이 필요 없습니다.
- 미끼 포트: 이 호스트에서 쓰지 않는 포트(기본값 23, 135, 1433, 3389, 5900, 6379 등)에 미끼를 두고, 접속하는 출처를 즉시 차단합니다.
- 포트 스캔 탐지: 같은 출처가 분당 임계값보다 많이 이 호스트의 열려 있지 않은 포트에 접속하면 차단합니다.
- 통합 차단 목록: 수동 차단(CIDR 네트워크와 영구 차단 지원)과 웹 서비스 인증 실패에 따른 자동 차단을 여기서 관리합니다. 차단은 저장되어 재시작 후에도 복원됩니다.
- 점진적 차단: 같은 주소가 30일 안에 다시 차단되면 시간이 두 배가 되며 상한까지 늘어납니다.
- 화이트리스트: LAN, 루프백, 100.64.0.0/10(Tailscale), 이 호스트 인터페이스가 속한 IPv6 /64는 기본적으로 무시합니다(차단이 /64 단위라 같은 LAN의 공인 IPv6 기기가 함께 차단되지 않도록). IP나 네트워크를 추가할 수 있으며, 화이트리스트의 단일 IPv6 주소는 그 /64 전체를 보호합니다.
적용 범위
| 환경 | 차단 효과 | 미끼 포트 | 포트 스캔 탐지 |
|---|---|---|---|
Linux(root 또는 CAP_NET_ADMIN, nftables 설치됨) | SSH, 다른 프로그램, Docker 컨테이너와 LAN 기기로 전달되는 트래픽까지 모두 커널에서 삭제 | 커널에서 처리, SYN만 보내는 스캔도 감지 | 사용 가능 |
Docker(host 네트워크 + cap_add: NET_ADMIN) | 위와 같음, 규칙은 호스트에 기록 | 위와 같음 | 사용 가능 |
| fnOS 패키지, OpenWrt 22.03 이상 | 위와 같음(root로 실행, nftables 기본 포함) | 위와 같음 | 사용 가능 |
| 그 밖의 경우(Windows, macOS, FreeBSD, nftables나 권한이 없는 Linux) | Gately 자체 서비스(포트 포워딩, 웹 서비스, STUN, WebDAV, FTP, 관리 콘솔)에만 적용 | Gately가 직접 수신, 핸드셰이크를 완료한 연결만 감지 | 사용 불가 |
페이지 상단에 방화벽 동기화 상태가 표시되며, 사용할 수 없으면 원인과 해결 방법을 보여 줍니다.
방화벽 규칙
"시스템 방화벽에 동기화"를 켜면 Gately는 nftables에 별도의 inet gately 테이블을 만들며, 시스템의 기존 규칙(fw4, Docker, ufw 등)은 건드리지 않습니다.
prerouting체인(우선순위 -190, 연결 추적 이후·목적지 NAT 이전)에서 차단된 주소가 보낸 패킷을 버립니다. 이 호스트로 오는 트래픽도, 컨테이너나 LAN 기기로 전달되는 트래픽도 버려집니다. 이 호스트가 먼저 연 연결(DNS, 패키지 미러 접속 등)의 응답은 상대 주소가 차단되어 있어도 그대로 통과합니다. IPv6는 /64 단위로 차단합니다.input체인은 이 호스트로 오는 새 연결만 보며, 미끼 포트와 스캔 탐지에 쓰입니다. 화이트리스트 주소는 제외됩니다.- 동기화를 끄거나 Gately를 중지하면 테이블 전체가 삭제됩니다. 다른 프로그램이 테이블을 지우면 10초 안에 다시 기록합니다.
페이지의 "규칙 보기"에서 현재 기록된 전체 규칙을 볼 수 있습니다.
Docker 배포
규칙을 호스트에 기록하려면 network_mode: host와 NET_ADMIN 권한이 필요합니다.
network_mode: host
cap_add:
- NET_ADMIN권한을 주지 않아도 차단은 Gately 자체 서비스에 적용됩니다. 호스트 로그를 읽으려면 로그 디렉터리를 컨테이너에 마운트하세요. 예를 들어 - /var/log:/var/log/host:ro로 마운트하고 규칙에 /var/log/host/auth.log를 입력합니다. systemd 저널 출처는 컨테이너에서 사용할 수 없습니다.
로그 규칙
| 출처 | 입력 | 설명 |
|---|---|---|
| 로그 파일 | 파일 경로, 한 줄에 하나 | 파일 끝에서부터 새 내용을 읽고 로테이션(이름 변경 또는 잘라내기)을 따라감 |
| systemd 저널 | ssh.service 같은 서비스 유닛 | journalctl -f로 읽음 |
| 명령 출력 | logread -f 같은 명령 하나 | 종료되면 자동으로 다시 시작 |
| Docker 컨테이너 | 컨테이너 이름 | Docker 관리 모듈이 연결한 Docker에서 읽음 |
| Gately 이벤트 | 관리 콘솔 로그인 실패 / WAF 차단 | 이벤트에 출처 IP가 포함되어 필터가 필요 없음 |
필터는 Go 정규식(RE2 문법)이며 한 줄에 하나씩, <HOST>가 출처 주소를 나타냅니다. 예:
Failed password for (?:invalid user )?\S* ?from <HOST>"제외"에 일치하는 줄은 세지 않습니다. 집계 기간, 실패 횟수, 차단 시간은 규칙마다 설정하며, 차단 시간은 기본값, 사용자 지정, 영구 중에서 고릅니다.
포트 스캔 탐지의 절충
스캔 탐지는 이 호스트가 수신하지 않는 포트로 오는 새 연결을 셉니다. 수신 중인 TCP 포트는 10초마다 갱신되어 열린 포트로 간주되며, 다른 방화벽 규칙으로 전달되는 포트는 input 체인을 거치지 않아 세지 않습니다. 기본 임계값은 분당 12회입니다. 일반 클라이언트가 닫힌 포트를 재시도하는 횟수는 분당 약 5회이므로 10 미만으로 낮추지 않는 것이 좋습니다.
미끼 포트 중 수신 중인 포트는 정상 방문자가 차단되지 않도록 자동으로 제외됩니다.
웹 서비스와의 관계
웹 서비스의 "인증 실패 시 차단"으로 생긴 차단도 같은 차단 목록에 들어가므로, 방화벽 동기화를 켜면 웹 사이트뿐 아니라 호스트 전체에 적용됩니다. "LAN 주소 무시"를 켜면 LAN 주소는 자동으로 차단되지 않습니다.
웹 서비스와 WAF는 PROXY 프로토콜로만 실제 클라이언트 주소를 알 수 있습니다. 실제 IP를 헤더로 전달하는 CDN 뒤의 사이트에서는 인증 실패 차단과 "WAF 차단" 규칙이 CDN 노드를 차단하게 되므로 이런 사이트에서는 켜지 마세요.
알림
차단하면 "침입 방지: IP 차단됨" 이벤트가 발생하며 알림 센터에서 구독할 수 있습니다. 미끼 포트와 스캔 탐지가 같은 점검에서 차단한 여러 주소는 하나의 알림으로 합쳐집니다.
검증
fnOS(Debian 12, nftables 1.0.6)와 iStoreOS 24.10(nftables 1.1.1)의 독립된 네트워크 네임스페이스에서 검증했습니다. 미끼 포트와 스캔 탐지(IPv4와 IPv6)가 커널에서 차단하고 차단 목록으로 가져오며, 로그 파일(로테이션 포함), systemd 저널, Docker 컨테이너 로그, 관리 콘솔 로그인 실패 모두 차단을 일으킵니다. 수동 네트워크·영구 차단, 차단 해제, 점진적 시간, 재시작 후 복원, 외부에서 삭제된 테이블의 재기록, 중지 시 규칙 정리도 기대대로 동작했고, NET_ADMIN이 없는 Docker 컨테이너는 권한 부족으로 판정되어 사용자 공간 미끼 포트로 전환됩니다.