13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 보안 체크리스트

  • [HomeLabs] 홈랩 네트워크 보안 강화: VLAN 기반 망 분리 체크리스트

    [HomeLabs] 홈랩 네트워크 보안 강화: VLAN 기반 망 분리 체크리스트

    홈랩 네트워크 보안 강화: VLAN 기반 망 분리 체크리스트

    안녕하세요, 13년차 서버실을 지키고 있는 인프라 엔지니어입니다. 요즘 홈랩 꾸미는 재미에 푹 빠져 계신 분들 많으시죠? 저도 그렇습니다! 그런데 홈랩이 커지면 커질수록 문득 ‘이대로 괜찮을까?’ 하는 불안감이 엄습할 때가 있더라고요. 특히 스마트 홈 기기들, 서버들, 그리고 개인 노트북과 스마트폰이 모두 같은 네트워크에 뒤섞여 있을 때 말이죠. 만약 IoT 기기 중 하나가 해킹당하면, 우리 집의 모든 소중한 데이터가 위험해질 수도 있겠다는 생각, 혹시 해보셨나요?

    제가 처음 홈랩을 구성했을 때도 그랬습니다. 편리함에만 집중하다 보니 보안은 뒷전이었죠. 그러다 문득 ‘기업 네트워크처럼 내 홈랩도 좀 더 안전하게 만들 수는 없을까?’ 하는 생각이 들더라고요. 그래서 VLAN(Virtual Local Area Network) 기반의 망 분리(Network Segmentation)를 직접 구현해보면서 많은 삽질을 했습니다. 오늘은 그 경험을 바탕으로, 여러분의 홈랩 네트워크 보안을 한층 강화할 수 있는 VLAN 기반 망 분리 체크리스트를 공유해볼까 합니다. 저의 시행착오를 통해 여러분은 좀 더 빠르고 안전하게 홈랩을 구축하시길 바랍니다. 🎉

    홈랩 네트워크 전체 아키텍처 다이어그램, VLAN 기반 망 분리 구성도

    홈랩 네트워크의 전체적인 구성과 VLAN으로 분리된 논리적 망을 보여주는 다이어그램입니다.

    VLAN과 망 분리, 왜 중요할까요?

    우선, 핵심 개념부터 잡고 갈게요. VLAN(Virtual Local Area Network, 가상 근거리 통신망)은 물리적으로는 하나의 스위치에 연결되어 있지만, 논리적으로는 여러 개의 독립적인 네트워크로 분리하는 기술입니다. 쉽게 말해, 한 아파트 건물에 살면서도 각 세대가 별도의 현관문을 가지고 독립적으로 생활하는 것과 비슷하다고 생각하시면 됩니다. 서로 다른 세대끼리는 함부로 드나들 수 없죠? 💡

    그리고 망 분리(Network Segmentation, 네트워크 세그멘테이션)는 이렇게 VLAN을 활용해서 전체 네트워크를 여러 개의 작은 논리적 네트워크로 나누는 작업을 의미합니다. 이게 왜 중요하냐면요:

    • 보안 강화: 만약 IoT 기기 하나가 해킹당하더라도, 해당 VLAN 내에서만 피해가 확산되고 다른 중요한 네트워크(예: 개인 PC가 있는 신뢰 네트워크)로는 침투하기 어려워집니다. Lateral Movement(측면 이동) 공격을 방지하는 데 아주 효과적이죠.
    • 성능 향상: 브로드캐스트 도메인을 분리하여 네트워크 트래픽 부담을 줄이고, 특정 네트워크의 트래픽이 다른 네트워크에 영향을 미치는 것을 최소화합니다.
    • 관리 용이성: 네트워크 정책을 특정 VLAN에만 적용하거나, 문제 발생 시 해당 VLAN만 격리하여 트러블슈팅 시간을 단축할 수 있습니다.

    특히 홈랩 네트워크 보안은 정말 중요하거든요. 외부 인터넷에 항상 노출되어 있고, 다양한 출처의 기기들을 연결하기 때문에 잠재적인 위협이 많거든요. 그래서 저는 망 분리를 ‘필수’라고 생각합니다.

    실전 구현: VLAN 기반 망 분리 체크리스트

    자, 이제 직접 홈랩에 VLAN을 적용해보는 실전 단계입니다. 준비물은 VLAN을 지원하는 매니지드 스위치(Managed Switch)와 VLAN 및 멀티 서브넷을 지원하는 라우터(예: pfSense, OpenWrt, MikroTik RouterOS 등)입니다. 저는 개인적으로 pfSense를 메인 라우터로 쓰고 있어서 이 환경에 맞게 설명드리겠지만, 개념은 대부분의 VLAN 지원 라우터에 적용 가능합니다.

    ✅ 1. 네트워크 설계 및 IP 주소 계획

    가장 먼저 할 일은 어떤 네트워크 존을 만들지, 그리고 각 존에 어떤 VLAN ID와 IP 대역을 할당할지 계획하는 겁니다. 이건 마치 건축 설계를 하는 것과 같아요. 대충 시작하면 나중에 큰코다칩니다. 😅

    • 관리 네트워크 (VLAN 1, 기본): 라우터, 스위치, NAS 등 핵심 인프라 장치 관리용. (예: 192.168.1.0/24)
    • 신뢰 네트워크 (VLAN 10): 개인 PC, 스마트폰 등 주로 사용하는 기기. (예: 192.168.10.0/24)
    • IoT 네트워크 (VLAN 20): 스마트 플러그, 카메라, 센서 등 IoT 기기. (예: 192.168.20.0/24)
    • 게스트 네트워크 (VLAN 30): 방문객을 위한 임시 Wi-Fi. (예: 192.168.30.0/24)

    이런 식으로 논리적인 구획을 나누는 게 첫걸음이에요. 각 VLAN ID는 1부터 4094까지 지정할 수 있는데, 보통 1은 기본 관리 VLAN으로 사용하니 다른 번호부터 시작하는 것이 좋습니다.

    ✅ 2. 라우터 설정: 서브 인터페이스 및 DHCP 서버 구성

    라우터에서 각 VLAN에 대한 서브 인터페이스(Sub-interface)를 생성하고, 해당 VLAN에 맞는 IP 주소와 DHCP 서버를 설정해야 합니다. 라우터가 각 VLAN의 게이트웨이 역할을 하게 되는 거죠.

    1. 라우터 관리 페이지에 접속합니다.
    2. ‘인터페이스(Interfaces)’ 또는 ‘VLAN 설정’ 메뉴로 이동합니다.
    3. 물리적 이더넷 포트(예: LAN 포트)에 대해 각 VLAN ID(예: 10, 20, 30)를 가진 서브 인터페이스를 생성합니다.
    4. 각 서브 인터페이스에 계획했던 IP 주소(예: 192.168.10.1, 192.168.20.1)를 할당합니다.
    5. 각 VLAN 인터페이스에 대한 DHCP 서버를 활성화하고, 해당 대역에서 IP 주소를 할당하도록 설정합니다.

    이 과정이 조금 복잡하게 느껴질 수도 있지만, 대부분의 홈랩용 라우터는 GUI로 쉽게 설정할 수 있게 되어 있습니다. 중요한 건 각 VLAN에 맞는 IP 대역과 게이트웨이를 정확히 설정하는 것입니다.

    ✅ 3. 스위치 설정: VLAN 생성 및 포트 할당

    이제 매니지드 스위치 차례입니다. 스위치에 접속해서 VLAN을 생성하고, 각 포트를 적절한 VLAN에 할당해야 합니다. 여기가 가장 핵심적인 부분 중 하나입니다.

    
    # 스위치에 로그인 후 전역 설정 모드로 진입 (장치에 따라 명령어 상이)
    configure terminal
    
    # VLAN 10 생성 및 이름 지정 (신뢰 네트워크용)
    vlan 10
     name TRUSTED_NETWORK
     exit
    
    # VLAN 20 생성 및 이름 지정 (IoT 네트워크용)
    vlan 20
     name IOT_NETWORK
     exit
    
    # VLAN 30 생성 및 이름 지정 (게스트 네트워크용)
    vlan 30
     name GUEST_NETWORK
     exit
    
    # 포트 1번을 VLAN 10 (신뢰)의 Access 포트로 설정
    # 여기에 개인 PC, Wi-Fi AP 등을 연결합니다.
    interface GigabitEthernet0/1
     switchport mode access
     switchport access vlan 10
     exit
    
    # 포트 5번을 VLAN 20 (IoT)의 Access 포트로 설정
    # 여기에 IoT 기기들을 연결합니다.
    interface GigabitEthernet0/5
     switchport mode access
     switchport access vlan 20
     exit
    
    # 포트 10번을 VLAN 30 (게스트)의 Access 포트로 설정
    # 게스트용 Wi-Fi AP 등을 여기에 연결할 수 있습니다.
    interface GigabitEthernet0/10
     switchport mode access
     switchport access vlan 30
     exit
    
    # 라우터와 연결될 포트 (예: 24번 포트)를 Trunk 모드로 설정
    # 모든 VLAN 트래픽이 이 포트를 통해 라우터로 전달됩니다.
    interface GigabitEthernet0/24
     switchport mode trunk
     switchport trunk allowed vlan 10,20,30
     # 혹은 모든 VLAN 허용: switchport trunk allowed vlan all
     exit
    
    # 설정 저장 (장치에 따라 명령어 상이: copy running-config startup-config, write memory 등)
    write memory
    end
    

    여기서 중요한 건 Access Port(액세스 포트)와 Trunk Port(트렁크 포트)의 개념입니다. Access Port는 특정 하나의 VLAN에만 속하는 포트로, 일반적인 종단 장치(PC, IoT 기기 등)를 연결할 때 사용합니다. 반면 Trunk Port는 여러 VLAN의 트래픽을 동시에 전달할 수 있는 포트로, 주로 라우터나 다른 스위치와 연결할 때 사용합니다. 라우터와 연결되는 포트는 반드시 Trunk 모드로 설정해야 합니다. ⚠️

    매니지드 스위치 VLAN 설정 및 포트 할당 완료 화면

    매니지드 스위치에서 각 VLAN을 생성하고 포트를 할당하는 설정 화면입니다.

    ✅ 4. 방화벽 규칙 설정: VLAN 간 통신 정책 정의

    마지막이자 가장 중요한 단계입니다. 라우터의 방화벽에서 각 VLAN 간의 통신 정책을 정의해야 합니다. VLAN으로 망 분리를 해놨다고 해서 끝이 아닙니다. 필요한 통신은 허용하고, 불필요한 통신은 엄격히 차단해야 진정한 보안 강화가 이루어집니다.

    기본적으로 라우터는 다른 서브넷 간의 통신을 허용하지만, VLAN을 분리한 목적이 보안 강화이므로 명시적으로 차단 규칙을 먼저 적용하고, 필요한 것만 허용하는 ‘Deny All, Allow Exception (기본 차단, 예외 허용)’ 정책을 사용하는 것이 좋습니다.

    예를 들어:

    • IoT 네트워크 ➡️ 신뢰 네트워크: 🚫 차단 (가장 중요!)
    • 신뢰 네트워크 ➡️ IoT 네트워크: ✅ 허용 (스마트폰으로 IoT 기기 제어 등)
    • 게스트 네트워크 ➡️ 모든 내부 네트워크: 🚫 차단 (오직 인터넷만 허용)
    • 모든 내부 네트워크 ➡️ 관리 네트워크: 🚫 차단, 단 관리 PC ➡️ 관리 네트워크는 ✅ 허용

    이 규칙들을 라우터의 방화벽 설정(예: pfSense의 Firewall Rules, OpenWrt의 Firewall Zones)에서 적용하면 됩니다. 처음엔 이 방화벽 규칙 때문에 삽질을 많이 했었는데, ‘어떤 트래픽이 어떤 방향으로 가야 하는가’를 명확히 정의하는 것이 핵심이더라고요. 하나씩 꼼꼼히 따져봐야 합니다.

    ⚠️ 주의사항 및 트러블슈팅 팁

    제가 직접 겪었던 문제들과 해결 팁을 공유해드릴게요. 아마 여러분도 비슷한 상황을 겪을 수 있을 겁니다.

    1. IP 주소를 못 받아와요! (DHCP 문제)
      라우터에서 해당 VLAN 인터페이스에 대한 DHCP 서버가 제대로 활성화되어 있는지, IP 풀(Pool) 범위는 올바른지 확인하세요. 스위치의 포트가 Access 모드로 잘 설정되어 있는지, VLAN ID가 정확한지 다시 한번 체크해봐야 합니다.
    2. 특정 VLAN끼리 통신이 안 돼요! (방화벽 문제)
      가장 흔한 문제입니다. 라우터의 방화벽 규칙을 다시 확인하세요. 기본적으로 VLAN 간 통신은 차단될 수 있으니, 필요한 통신은 명시적으로 ‘허용(Allow)’ 규칙을 추가해야 합니다. 로그를 확인하면 어떤 트래픽이 차단되는지 알 수 있습니다.
    3. VLAN 태그가 안 먹어요! (Trunk/Access 포트 설정 오류)
      라우터와 스위치를 연결하는 포트가 Trunk 모드로 설정되었는지, 그리고 허용된 VLAN 목록이 정확한지 확인해야 합니다. 일반 장치를 연결하는 포트는 Access 모드여야 하고, 할당된 VLAN ID가 정확한지 보세요. 태그가 없는(Untagged) 트래픽과 태그가 있는(Tagged) 트래픽의 개념을 이해하는 게 중요합니다.

    ✅ 검증: 제대로 작동하는지 확인하기

    모든 설정을 마쳤다면, 이제 제대로 작동하는지 확인해야겠죠? 저는 주로 다음 방법들을 사용합니다.

    
    # 1. 클라이언트 장치에서 IP 주소 확인
    # VLAN이 잘 적용되었다면, 해당 VLAN에 맞는 IP 대역을 받을 겁니다.
    # 예: IoT 기기는 192.168.20.x 대역을 받아야 합니다.
    ip addr show
    
    # 예시 출력 (enp0s31f6.20은 VLAN 20 인터페이스)
    # ...
    # 3: enp0s31f6.20@enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    #     link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff
    #     inet 192.168.20.50/24 brd 192.168.20.255 scope global dynamic enp0s31f6.20
    #        valid_lft 3599sec preferred_lft 3599sec
    # ...
    
    # 2. 다른 VLAN 대역의 장치로 Ping 테스트
    # 차단되어야 하는 네트워크로는 ping이 가지 않아야 합니다.
    # 예: IoT 네트워크에서 신뢰 네트워크 장치(192.168.10.10)로 Ping 시도 시 실패 예상
    ping 192.168.10.10
    
    # 예: IoT 네트워크에서 IoT 게이트웨이(192.168.20.1)로 Ping 시도 시 성공 예상
    ping 192.168.20.1
    
    # 3. 라우터의 방화벽 로그 확인
    # 라우터 관리 페이지에서 방화벽 로그를 확인하여 차단된 트래픽이 올바른지 검증합니다.
    # 예상치 못한 차단이나, 허용되어야 할 트래픽이 차단되는 경우 규칙을 조정해야 합니다.
    

    이런 테스트를 통해 각 VLAN이 의도한 대로 분리되었고, 방화벽 규칙도 제대로 작동하는지 확인할 수 있습니다. 저는 이 과정을 여러 번 반복하면서 ‘드디어 됐다!’ 하고 외쳤던 기억이 나네요. 🎉

    VLAN별 네트워크 트래픽 및 방화벽 차단 로그 모니터링 대시보드

    VLAN별 트래픽 흐름이나 방화벽 차단 로그를 보여주는 모니터링 대시보드 예시입니다.

    마무리하며: 홈랩 네트워크 보안은 선택이 아닌 필수!

    지금까지 홈랩 네트워크 보안을 강화하기 위한 VLAN 기반 망 분리 체크리스트를 자세히 살펴봤습니다. 13년차 인프라 엔지니어로서 제가 수많은 삽질 끝에 얻은 결론은, ‘홈랩 네트워크 보안은 이제 선택이 아닌 필수’라는 겁니다. 특히 IoT 기기들이 늘어나면서 보안 위협도 기하급수적으로 증가하고 있거든요.

    어떤 홈랩 환경이든, 최소한 ‘신뢰 네트워크’와 ‘IoT/게스트 네트워크’는 반드시 분리하는 것을 강력히 권장합니다. 저처럼 처음부터 완벽하게 모든 것을 나누기 어렵다면, 가장 취약하다고 생각되는 부분부터 점진적으로 분리해나가는 것도 좋은 방법입니다. VLAN 설정은 한 번 해두면 두고두고 든든한 방어막이 되어줄 겁니다.

    네트워크 존 (VLAN ID) 설명 주요 연결 장치 보안 정책 (라우터 방화벽)
    관리 네트워크 (VLAN 1) 라우터, 스위치, NAS 등 핵심 인프라 장치 관리용. 관리 PC, NAS, 서버 모든 내부 네트워크 접근 허용, 외부 접근 엄격히 제한
    신뢰 네트워크 (VLAN 10) 주로 사용하는 PC, 스마트폰 등 개인 기기. 인터넷 접근 허용. 개인 PC, 스마트폰, 태블릿 외부 인터넷 및 관리 네트워크 접근 허용, IoT/게스트 네트워크 접근 차단
    IoT 네트워크 (VLAN 20) 스마트 플러그, 전구, 로봇 청소기 등 IoT 기기. 스마트 플러그, 카메라, 센서 외부 인터넷 제한적 허용 (필요한 서버만), 신뢰/관리 네트워크 접근 차단
    게스트 네트워크 (VLAN 30) 방문객을 위한 임시 네트워크. 방문객 스마트폰, 노트북 외부 인터넷만 허용, 모든 내부 네트워크 접근 차단
    VLAN 기반 망 분리 이점 및 핵심 단계 요약 인포그래픽

    VLAN 기반 망 분리의 주요 이점과 핵심 설정 단계를 한눈에 볼 수 있는 요약 정보입니다.

    다음번에는 이렇게 분리된 네트워크에 침입 탐지 시스템(IDS/IPS)을 어떻게 적용해서 보안을 한층 더 고도화할 수 있는지, 제가 직접 구축한 경험을 바탕으로 이야기해보는 시간을 가져볼까 합니다. 궁금하시다면 다음 글도 기대해주세요! 그럼 오늘도 안전하고 즐거운 홈랩 생활 되시길 바랍니다. 😊

  • [보안] 리눅스 서버 하드닝 전략 재점검 체크리스트

    [보안] 리눅스 서버 하드닝 전략 재점검 체크리스트

    리눅스 서버 하드닝 전략 재점검 체크리스트

    요즘 보안 메일함 열어보면 심장이 조금 빨리 뛰죠. 특히 리눅스 서버 하드닝 관점에서 보면, 커널과 사용자 공간(User space, 커널 밖에서 도는 일반 프로세스) 취약점 공지가 꽤 자주 올라옵니다. 저도 홈랩이랑 운영 서버를 같이 굴리다 보니, 처음엔 “요즘 왜 이렇게 Linux CVE가 많아졌지?” 싶었거든요. 그런데 실제로 뜯어보니, 단순히 숫자만 늘었다기보다 공개 체계가 더 촘촘해진 부분, 그리고 실제로 빨리 패치해야 하는 취약점이 섞여 있더라고요.

    특히 2024년 2월 13일에 kernel.org가 CVE Numbering Authority(CNA, CVE 번호 발급 권한 기관)로 추가된 뒤부터는 Linux 커널 취약점에 CVE가 더 체계적으로 붙기 시작했습니다. 거기에 CISA가 실제 악용 사례가 있는 Linux kernel 취약점들을 Known Exploited Vulnerabilities(KEV) 목록에 올리면서, “아, 이건 숫자 구경만 할 게 아니구나” 싶었거든요. 리눅스 보안은 결국 패치 속도만의 문제가 아니라, 노출면(Attack Surface, 공격 가능 면적)을 줄이는 운영 습관의 문제이기도 합니다.

    리눅스 서버 하드닝 전체 구조를 보여주는 아키텍처 이미지

    커널, SSH, 방화벽, MAC 정책, 패치 자동화, 검증 흐름까지 한눈에 보여주는 개요 이미지입니다.

    1. 최근 Linux CVE가 많이 보이는 이유부터 정리해보겠습니다

    쉽게 말해, 요즘 보이는 “급증”은 두 가지가 섞여 있습니다. 발견과 공개가 더 적극적이 된 점, 그리고 실제 운영자가 체감할 정도로 대응 압박이 커진 점이 같이 온 겁니다.

    구분 무슨 뜻인가 운영자가 봐야 할 포인트
    CVE 공개 체계 변화 kernel.org가 2024-02-13부터 CNA 역할 수행 이전보다 커널 취약점이 더 잘 드러날 수 있음
    실제 악용 사례 CISA가 Linux kernel CVE를 KEV에 추가 패치 우선순위를 높게 잡아야 함
    자동화된 버그 탐지 fuzzing과 정적/동적 분석이 더 활발 작은 버그도 더 빨리 공론화됨

    여기서 중요한 포인트가 있습니다. CVE 숫자가 늘었다 = 리눅스가 갑자기 위험해졌다로 바로 연결하면 좀 단순합니다. 제가 직접 홈랩 커널 업데이트 흐름을 따라가 보니까, 예전엔 배포판 공지 뒤에 숨어 지나가던 수정이 이제는 CVE로 더 명확하게 드러나는 경우도 꽤 있더라고요. 반대로, KEV에 들어간 건 진짜 우선순위가 다릅니다. 이건 “나중에 점검”이 아니라 즉시 확인 쪽입니다.

    2. 리눅스 서버 하드닝 체크리스트, 우선순위는 이렇게 잡으시면 됩니다

    저는 보통 패치, 접근 통제, 권한 축소, 관측성 순으로 봅니다. 이유는 간단하거든요. 멋진 보안 솔루션보다 먼저, 뚫릴 구멍을 줄이는 게 훨씬 싸고 빠릅니다.

    1. 커널과 패키지 업데이트 기준선 만들기: 지금 어떤 커널을 쓰는지, 보안 업데이트가 몇 건 밀렸는지 숫자로 확인합니다.
    2. SSH 노출면 줄이기: 비밀번호 로그인, root 직접 로그인, 불필요한 포트 노출을 먼저 줄입니다.
    3. 방화벽 기본 정책 정리: 허용 목록(Allowlist, 허용 대상만 열기) 방식으로 바꿉니다.
    4. SELinux/AppArmor 같은 MAC 적용: 뚫려도 옆으로 번지는 걸 막습니다.
    5. systemd sandboxing: 서비스 단위로 권한을 더 잘게 자릅니다.
    6. 감사 로그와 검증 루틴: 적용 후 확인하지 않으면 하드닝이 아니라 기분만 좋아지는 설정이 됩니다.

    3. 실전 구현 1단계: 패치 상태와 커널 노출 범위부터 확인합니다

    처음엔 이게 뭔가 싶었는데, 결국 출발점은 단순합니다. 무엇이 돌아가고 있는지 알아야 CVE 대응도 빠릅니다. 아래 명령은 제가 새 서버 잡으면 거의 습관처럼 먼저 칩니다.

    uname -r
    cat /etc/os-release
    ss -tulpn
    systemctl --failed
    

    uname -r은 현재 커널 버전, ss -tulpn은 외부에 열려 있는 포트와 프로세스를 같이 보여줍니다. 여기서 예상 밖 포트가 보이면, 그 서버는 이미 서버 보안 강화 대상입니다.

    Debian/Ubuntu 계열이면 보안 업데이트 확인은 이렇게 시작하시면 됩니다.

    sudo apt update
    apt list --upgradable
    sudo unattended-upgrades --dry-run -d
    

    RHEL 계열은 보통 이렇게 봅니다.

    sudo dnf check-update
    sudo dnf updateinfo list security
    

    Ubuntu를 쓰신다면 Livepatch(재부팅 없이 일부 커널 보안 수정 적용)도 검토할 만합니다. 다만 Canonical 문서 기준으로 Livepatch만 믿고 장기간 재부팅을 미루면 안 됩니다. 지원되는 커널 ABI 범위와 재부팅 주기가 따로 있거든요. 실제로 써보니까 편하기는 한데, 이것도 결국 정식 커널 교체를 완벽히 대체할 수는 없더라고요.

    4. 실전 구현 2단계: SSH와 네트워크부터 조입니다

    제가 제일 먼저 손대는 부분입니다. CVE가 터졌을 때 제일 아쉬운 서버가 어떤 서버냐 하면, 패치가 늦은 서버보다도 불필요하게 다 열어둔 서버더라고요. 삽질 좀 했습니다 ㅎㅎ

    sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
    sudoedit /etc/ssh/sshd_config
    
    PermitRootLogin no
    PasswordAuthentication no
    KbdInteractiveAuthentication no
    PubkeyAuthentication yes
    MaxAuthTries 3
    AllowUsers adminops
    

    적용 전에는 반드시 문법 검사를 하세요.

    sudo sshd -t && sudo systemctl reload sshd
    

    방화벽은 nftables 기준으로 아주 단순하게 시작하는 편이 좋습니다.

    sudo mkdir -p /etc/nftables
    sudoedit /etc/nftables.conf
    
    #!/usr/sbin/nft -f
    flush ruleset
    
    table inet filter {
      chain input {
        type filter hook input priority 0;
        policy drop;
        iif lo accept
        ct state established,related accept
        tcp dport { 22, 80, 443 } accept
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept
      }
    
      chain forward {
        type filter hook forward priority 0;
        policy drop;
      }
    
      chain output {
        type filter hook output priority 0;
        policy accept;
      }
    }
    
    sudo nft -f /etc/nftables.conf
    sudo nft list ruleset
    sudo systemctl enable --now nftables
    
    리눅스 서버 하드닝에서 SSH와 방화벽 정책을 설명하는 이미지

    SSH 접근 제한, 허용 포트 최소화, 상태 기반 방화벽 정책을 시각적으로 보여주는 이미지입니다.

    5. 실전 구현 3단계: SELinux, AppArmor, systemd sandboxing으로 한 번 더 막습니다

    Mandatory Access Control(MAC, 강제 접근 통제)은 초반엔 귀찮아 보여도, 사고 났을 때 진짜 값어치를 합니다. Red Hat 문서도 SELinux를 추가 보안 계층으로 설명하고 있고, Ubuntu 문서도 AppArmor를 경로 기반 MAC으로 안내합니다. 쉽게 말해 프로세스가 원래 해야 할 일만 하게 만드는 장치입니다.

    RHEL 계열에서는 SELinux 상태를 먼저 확인하세요.

    getenforce
    sestatus
    sudo setenforce 1
    

    Ubuntu 계열에서는 AppArmor 상태를 확인합니다.

    sudo apparmor_status
    sudo aa-enforce /etc/apparmor.d/*
    

    그리고 요즘 제가 자주 같이 보는 게 systemd-analyze security입니다. 서비스별 노출 점수를 빠르게 볼 수 있어서, 감으로 하드닝하는 느낌이 훨씬 줄어들더라고요.

    sudo systemd-analyze security nginx.service
    

    서비스 오버라이드(override)로 샌드박싱을 추가하는 예시는 아래처럼 시작하시면 됩니다.

    sudo systemctl edit nginx.service
    
    [Service]
    NoNewPrivileges=yes
    PrivateTmp=yes
    ProtectSystem=strict
    ProtectHome=yes
    PrivateDevices=yes
    RestrictSUIDSGID=yes
    LockPersonality=yes
    MemoryDenyWriteExecute=yes
    RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
    SystemCallArchitectures=native
    
    sudo systemctl daemon-reload
    sudo systemctl restart nginx
    sudo systemd-analyze security nginx.service
    

    이거 실제로 써보니까 꽤 좋더라고요. 다만 여기서 중요한 건, 서비스별로 필요한 권한이 다르다는 점입니다. DB나 백업 에이전트는 너무 세게 조이면 바로 깨집니다.

    6. 커널 노출면 줄이는 sysctl과 감사 로그도 같이 가야 합니다

    리눅스 서버 하드닝에서 빠지기 쉬운 게 커널 파라미터와 로그입니다. 공격 자체를 막는 것도 중요하지만, 이상 징후를 빨리 보는 것도 중요하거든요.

    sudoedit /etc/sysctl.d/99-hardening.conf
    
    net.ipv4.conf.all.accept_redirects = 0
    net.ipv4.conf.default.accept_redirects = 0
    net.ipv4.conf.all.send_redirects = 0
    net.ipv4.conf.default.send_redirects = 0
    net.ipv4.conf.all.rp_filter = 1
    net.ipv4.conf.default.rp_filter = 1
    net.ipv4.tcp_syncookies = 1
    kernel.kptr_restrict = 2
    kernel.dmesg_restrict = 1
    fs.protected_symlinks = 1
    fs.protected_hardlinks = 1
    
    sudo sysctl --system
    

    감사 로그(audit log)도 최소한은 잡아두는 편이 좋습니다.

    sudo apt install auditd -y || sudo dnf install audit -y
    sudo systemctl enable --now auditd
    
    sudo auditctl -w /etc/ssh/sshd_config -p wa -k ssh_config_change
    sudo auditctl -w /etc/sudoers -p wa -k sudoers_change
    sudo auditctl -w /usr/bin/sudo -p x -k sudo_exec
    

    여기서 정말 중요한 포인트예요. 로그는 쌓는 것보다 어떤 이벤트를 보면 위험 신호로 판단할지가 더 중요합니다. SSH 설정 변경, sudo 실행 급증, 예상하지 못한 서비스 재시작 같은 건 바로 알아채야 하거든요.

    리눅스 서버 하드닝에서 SELinux AppArmor 시스템 샌드박싱을 보여주는 이미지

    프로세스 권한 최소화와 서비스 격리를 여러 층으로 적용하는 장면을 표현한 이미지입니다.

    7. ⚠️ 실제로 자주 겪는 문제와 트러블슈팅

    하드닝은 설정 넣는 순간보다, 그 뒤에 안 깨지게 만드는 과정이 더 어렵습니다. 저도 처음엔 자신 있게 적용했다가 웹 서비스가 파일 못 읽어서 502 띄운 적 있습니다.

    • SELinux/AppArmor 적용 후 서비스 장애: 먼저 비활성화하지 말고 로그를 봅니다. SELinux는 /var/log/audit/audit.log, AppArmor는 journalctl -xe나 /var/log/syslog 쪽부터 확인하세요.
    • systemd sandboxing 후 서비스 기동 실패: ProtectSystem=strict, ProtectHome=yes가 자주 원인입니다. 서비스가 실제로 써야 하는 경로를 ReadWritePaths=로 열어줘야 할 수 있습니다.
    • SSH 설정 변경 후 원격 접속 끊김: 운영 중인 세션을 유지한 상태에서 새 세션으로 테스트하고, 가능하면 콘솔 접근 수단을 남겨두세요.
    • 방화벽 적용 후 내부 통신 장애: 모니터링, 백업, 노드 간 헬스체크 포트를 빼먹는 경우가 많습니다. 홈랩에서 Kubernetes 올릴 때 저도 이걸로 반나절 썼습니다.

    그래서 저는 항상 한 번에 다 바꾸지 않고, 서비스 하나씩 묶어서 적용합니다. 보안 체크리스트는 체크만 하면 끝나는 문서가 아니라, 배포 순서를 정리하는 운영 문서여야 하더라고요.

    8. 검증, 결과 확인, 그리고 다음 단계

    설정이 들어갔으면 반드시 검증해야 합니다. 아래 정도는 최소 루틴으로 가져가면 좋습니다.

    1. 커널/패키지 버전 확인: 패치 적용 전후 버전 차이를 기록합니다.
    2. 포트 노출 재검사: ss -tulpn 결과를 저장해 비교합니다.
    3. 서비스 샌드박스 점검: systemd-analyze security로 전후 점수를 비교합니다.
    4. 로그 확인: SELinux/AppArmor 거부 로그, audit 로그, 인증 로그를 같이 봅니다.
    5. 재부팅 리허설: 커널 업데이트 후 서비스가 정상 복구되는지 꼭 확인합니다.
    uname -r
    ss -tulpn
    sudo systemd-analyze security
    sudo journalctl -p warning -b
    sudo ausearch -k ssh_config_change
    

    제가 직접 해보니 가장 효과가 큰 건 화려한 솔루션이 아니라 패치 기준선 + SSH 제한 + 방화벽 기본 거부 + MAC + 서비스 샌드박스 이 5개였습니다. 드디어 됐다! 싶은 순간이 오긴 오는데, 사실 그 뒤가 더 중요합니다. 운영 환경은 계속 바뀌니까요.

    리눅스 서버 하드닝 적용 전후 결과를 보여주는 검증 이미지

    적용 전후 비교 결과를 대시보드 형태로 보여주는 검증 이미지입니다.

    정리: 지금 바로 다시 볼 체크포인트

    • 리눅스 서버 하드닝은 CVE 개수보다 노출면 축소가 핵심입니다.
    • kernel.org CNA 전환과 실제 악용 사례 공개를 보면, 공개량 증가와 실제 위험 신호를 구분해서 봐야 합니다.
    • CVE 대응은 패치만이 아니라 SSH, nftables, SELinux/AppArmor, systemd sandboxing까지 묶어서 봐야 합니다.
    • 검증 없는 하드닝은 절반짜리입니다. 적용 후 로그와 서비스 상태를 꼭 확인하세요.

    다음 글에서는 systemd 서비스별 하드닝 템플릿을 좀 더 깊게 다뤄볼 예정입니다. 이전 글에서 다뤘던 로그 수집 파이프라인이 있으시면 그쪽과 묶어서 보셔도 좋고요.

    패치, 접근 통제, MAC, 샌드박스, 로그 검증을 우선순위별로 정리한 요약 이미지입니다.

    참고한 공개 자료

  • [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    서버를 올리고 포트만 열어둔 뒤 불안했던 경험, 아마 한 번쯤 있으실 겁니다. 저도 홈랩에서 테스트 서버를 굴리다가 방화벽 설정을 대충 해두고 넘어갔다가 나중에 로그를 보고 식은땀을 흘린 적이 있거든요. 방화벽 설정은 단순히 포트를 열고 닫는 작업이 아니라, 네트워크 보안의 기본선(baseline, 최소 보안 기준)을 만드는 일입니다. 이번 글에서는 실무와 홈랩에서 반복해서 확인하는 방화벽 보안 체크리스트 중심으로, 꼭 봐야 할 필수 점검 항목 10가지를 정리해보겠습니다.

    특히 이 글은 “방화벽 설정 후 뭘 먼저 확인해야 하지?” 하고 막막하신 분들을 위해 썼습니다. Linux 서버 기준 예시를 넣겠지만, 원칙 자체는 온프레미스(on-premise, 사내 구축 환경), 클라우드, 가상화 환경 모두에 그대로 적용됩니다.

    방화벽 설정이 적용된 홈랩 네트워크 아키텍처 이미지

    방화벽 설정 점검 항목이 DMZ, 내부망, 관리망으로 나뉘어 보이는 전체 개요 이미지입니다.

    1. 왜 방화벽 설정 점검은 항상 사고 전에 해야 할까요

    방화벽(Firewall, 트래픽을 제어하는 보안 장치)은 평소엔 조용합니다. 그래서 더 무섭습니다. 문제가 생기기 전까지는 존재감이 없거든요. 그런데 실제 장애나 침해사고 대응에서는 거의 항상 “이 포트 왜 열려 있었지?”, “관리 포트가 왜 외부에 노출됐지?” 같은 질문이 나옵니다.

    제가 직접 경험해보니 방화벽 설정 검토는 잘한 티는 안 나는데, 한 번 놓치면 문제가 됩니다. 특히 다음 상황에서 실수가 많이 나옵니다.

    • 테스트 서버를 운영 서버처럼 오래 끌고 갔을 때
    • 임시 오픈한 포트를 닫지 않았을 때
    • 소스 IP 제한 없이 관리 포트를 공개했을 때
    • 클라우드 보안 그룹(Security Group, 가상 방화벽)과 OS 방화벽 정책이 따로 놀 때

    여기서 중요한 포인트는 이것입니다: 방화벽은 “설정해뒀다”보다 “지금도 맞는 상태인지 확인하는 것”이 더 중요합니다.

    2. 좋은 방화벽 설정의 기본 원칙

    좋은 방화벽 설정은 결국 한 문장으로 정리됩니다: 필요한 통신만 허용하고, 나머지는 기본 차단(Default Deny, 기본 거부)하는 상태입니다. 이 원칙 하나만 제대로 잡아도 절반은 갑니다.

    방화벽 설정 점검 기준은 세 가지로 보면 편합니다.

    1. 누가 들어오나: 소스 IP, 네트워크 대역
    2. 어디로 들어오나: 목적지 포트, 서비스
    3. 왜 열어두나: 실제 업무 필요성, 운영 근거

    결국 방화벽 설정은 ACL(Access Control List, 접근 제어 목록)을 얼마나 명확하게 관리하느냐의 문제더라고요. “웹 서비스라서 80/443 허용”, “운영자만 SSH 22 접근”, “DB 3306은 앱 서버만 허용” 이런 식으로요.

    3. 방화벽 설정 점검 체크리스트: 필수 10가지 항목

    아래 10가지는 제가 서버 오픈 전에 거의 습관처럼 확인하는 필수 점검 항목입니다. 이 순서로 보면 빠르고, 빠뜨릴 것도 줄어듭니다.

    항목 무엇을 확인하나 핵심 이유
    1 기본 정책(Default Policy) 미정의 트래픽 차단
    2 허용 포트 최소화 공격 표면 축소
    3 관리 포트 접근 제한 SSH, RDP 등 보호
    4 소스 IP 대역 제한 불필요한 외부 접근 차단
    5 인바운드/아웃바운드 구분 양방향 정책 명확화
    6 불필요한 Any 허용 제거 과도한 허용 방지
    7 로그 활성화 추적과 감사 가능
    8 규칙 우선순위 확인 예상과 다른 매칭 방지
    9 예외 정책 문서화 운영 지속성 확보
    10 검증 명령과 정기 점검 설정 드리프트 방지

    보안 체크리스트는 화려할 필요 없습니다. 대신 반복 가능해야 합니다. 그리고 누가 봐도 같은 결론이 나와야 합니다.

    10가지 필수 항목을 짧게 풀어보면

    • 기본 정책은 deny: 허용보다 차단을 기본값으로 둡니다.
    • 포트는 최소한만: 서비스와 무관한 포트는 닫습니다.
    • 관리 포트는 외부 전체 공개 금지: Bastion(배스천, 중계 관리 서버)이나 VPN 뒤로 넣는 게 좋습니다.
    • 소스 제한: 가능하면 특정 사무실 IP나 관리망만 허용합니다.
    • 아웃바운드도 본다: 내부 서버가 외부로 아무 데나 나가는 것도 위험할 수 있습니다.
    • Any-Any 규칙 제거: 편하지만 위험합니다. 저도 급할 때 열었다가 나중에 후회했었습니다.
    • 로그는 꼭 남긴다: 침해 대응의 시작점입니다.
    • 우선순위 확인: 먼저 걸리는 규칙 때문에 뒤 규칙이 무의미해질 수 있습니다.
    • 예외는 기록: 왜 열었는지 안 적어두면 몇 달 뒤 아무도 모릅니다.
    • 정기 검증: 월 1회만 해도 효과가 큽니다.

    4. 실전 구현: Linux 서버의 방화벽 설정 기본

    여기서는 Ubuntu 계열에서 많이 쓰는 UFW(Uncomplicated Firewall, 간단 방화벽 관리 도구) 기준으로 보여드리겠습니다. 환경에 따라 nftables(리눅스 패킷 필터 프레임워크)나 iptables(전통적 패킷 필터)를 쓰실 수도 있는데, 원칙은 같습니다.

    1. 현재 열려 있는 서비스와 포트를 먼저 확인합니다.
    2. 기본 정책을 설정합니다.
    3. 서비스별 허용 규칙을 최소 권한으로 추가합니다.
    4. 로그와 검증을 수행합니다.
    ss -tulpn
    sudo ufw status verbose
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
    sudo ufw logging on
    sudo ufw enable
    sudo ufw status numbered

    위 예시는 정말 기본형입니다. 웹 서버라면 80/443만, SSH는 관리 IP에서만 허용하는 식이죠. 실제로 써보니까 처음부터 이렇게 보수적으로 잡는 게 나중에 훨씬 편하더라고요.

    서비스별 방화벽 설정 기준

    서비스 권장 접근 방식 비고
    SSH 특정 관리 IP만 허용 가능하면 VPN 뒤에서 접근
    HTTP/HTTPS 외부 공개 허용 리버스 프록시 뒤 구성 가능
    DB 포트 앱 서버 IP만 허용 인터넷 직접 공개 지양
    모니터링 포트 관리망만 허용 Prometheus 등 내부 수집 권장
    방화벽 설정에서 허용 포트를 구분한 서버 구성 이미지

    웹 포트와 관리 포트가 구분되어 보이는 실전 방화벽 설정 예시 이미지입니다.

    5. 더 실무적으로: 인바운드와 아웃바운드를 함께 점검하세요

    많이 놓치는 부분이 아웃바운드(Outbound, 서버에서 외부로 나가는 트래픽)입니다. 인바운드만 막아두면 끝이라고 생각하기 쉬운데, 실제 운영에서는 그렇지 않거든요. 만약 서버가 침해당했다면 외부 C2(Command and Control, 원격 제어 서버)와 통신을 시도할 수도 있습니다.

    그래서 저는 최소한 아래는 꼭 봅니다.

    • 패키지 저장소, 시간 동기화, 외부 API 등이 꼭 필요한 목적지인지
    • 내부 서버가 임의 포트로 외부에 나가고 있지 않은지
    • 백업, 모니터링, 알림 전송 경로가 정책과 충돌하지 않는지

    예를 들어 DB 서버는 인터넷으로 직접 나갈 이유가 거의 없습니다. 그런 서버는 아웃바운드 정책도 보수적으로 잡는 편이 낫습니다.

    sudo ufw default deny outgoing
    sudo ufw allow out 53
    sudo ufw allow out 123/udp
    sudo ufw allow out 443/tcp
    sudo ufw status verbose

    물론 이렇게 하면 처음엔 업데이트나 에이전트 통신이 막혀서 좀 삽질했습니다. ㅎㅎ 그래서 운영 서버에 바로 적용하기보다는, 먼저 필요한 통신 목록부터 뽑아보시는 걸 추천드립니다.

    6. 규칙 우선순위, 로그, 문서화: 운영 품질을 갈라놓는 세 가지

    방화벽 설정이 당장은 맞아 보여도, 시간이 지나면 예외 규칙이 늘어나면서 복잡해집니다. 그때 진짜 차이가 나는 게 규칙 우선순위(rule order), 로그(logging), 문서화(documentation)입니다.

    규칙 우선순위 확인하기

    특히 iptables나 클라우드 ACL에서는 먼저 매칭된 규칙이 적용되는 경우가 많습니다. 그래서 아래처럼 번호나 순서를 보고 정리해야 합니다.

    sudo ufw status numbered

    분명 차단 규칙을 넣었는데 접속이 되는 경험 있으신가요? 나중에 보면 위쪽에 더 넓은 허용 규칙이 먼저 있더라고요. 저도 처음엔 꽤 헷갈렸습니다.

    로그는 최소한 이 정도는 남기세요

    • 거부된 접속 시도
    • 관리 포트 접근 시도
    • 비정상적으로 반복되는 스캔 패턴

    로그가 있어야 Fail2ban 같은 자동 방어 도구를 붙이기도 쉽고, 나중에 보안 체크리스트 점검 결과를 설명하기도 편합니다.

    예외 정책은 꼭 기록하세요

    예를 들어 “협력사 고정 IP에서만 임시 허용, 만료일은 2026-08-03” 같은 걸 남겨야 합니다. 안 그러면 임시가 영구가 됩니다. 이거 진짜 자주 봅니다.

    방화벽 설정 결과를 모니터링하는 네트워크 보안 대시보드 이미지

    차단 로그와 관리 포트 접근 시도가 보이는 결과 검증용 모니터링 이미지입니다.

    7. ⚠️ 실제로 겪었던 문제들: 방화벽 트러블슈팅 포인트

    실무든 홈랩이든 방화벽 설정에서 가장 무서운 건 “서비스를 보호하려다가 내가 못 들어가는 상황”입니다. 저도 원격지 장비에서 SSH를 제 손으로 막아본 적 있습니다. “드디어 됐다!” 하고 나갔는데 다시 접속이 안 되더라고요.

    자주 겪는 문제 1: SSH를 너무 빨리 막음

    해결 방법은 간단합니다: 현재 접속 중인 세션을 유지한 상태에서 새 세션으로 재접속 테스트를 먼저 하세요.

    sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
    ssh user@server-ip

    새 세션 접속이 확인되기 전에는 기존 세션을 끊지 않는 게 안전합니다.

    자주 겪는 문제 2: 클라우드 방화벽과 OS 방화벽이 충돌

    AWS Security Group, GCP VPC Firewall, Azure NSG 같은 상위 정책과 OS 내부 정책이 둘 다 있으면, 어디서 막히는지 헷갈립니다. 이런 경우는 아래 순서로 확인하면 됩니다.

    1. 클라우드 보안 그룹에서 허용 여부 확인
    2. OS 방화벽에서 동일 포트 허용 여부 확인
    3. 서비스 데몬이 실제로 Listen(포트 대기) 중인지 확인
    4. 라우팅과 NAT(Network Address Translation, 주소 변환) 경로 확인
    ss -tulpn
    sudo ufw status verbose
    ip addr
    ip route

    자주 겪는 문제 3: IPv4만 보고 끝냄

    이 부분도 은근히 놓칩니다. IPv6이 활성화된 환경이라면 IPv4 규칙만 보고 안심하면 안 됩니다. 방화벽 설정 점검 시 IPv6 정책도 같이 봐야 합니다.

    8. 검증 방법: 설정했으면 반드시 확인하세요

    보안은 추측으로 끝내면 안 됩니다. 설정 후에는 꼭 검증해야 합니다. 저는 보통 서버 내부 확인과 외부 확인을 나눠서 봅니다.

    서버 내부에서 확인

    sudo ufw status verbose
    sudo ufw status numbered
    ss -tulpn
    • 열려 있어야 하는 포트만 열려 있는지
    • 허용 대상 IP가 의도와 맞는지
    • 기본 정책이 incoming deny인지

    외부에서 확인

    nc -vz server-ip 22
    nc -vz server-ip 80
    nc -vz server-ip 443

    관리 PC에서는 열려야 하고, 허용되지 않은 위치에서는 막혀야 정상입니다. 이 차이를 직접 확인해보면 훨씬 마음이 놓입니다.

    방화벽 설정 검증 체크리스트

    1. 기본 정책이 차단 중심인지 확인
    2. 불필요한 포트가 남아 있지 않은지 확인
    3. 관리 포트가 특정 IP로 제한됐는지 확인
    4. 로그가 남고 있는지 확인
    5. 예외 정책이 문서화됐는지 확인

    이 정도만 해도 네트워크 보안 수준이 꽤 안정됩니다. 화려한 장비보다 이런 기본기가 훨씬 오래 갑니다.

    방화벽 설정 필수 점검 항목을 요약한 네트워크 보안 이미지

    점검 전후 차이와 필수 점검 항목 10가지를 한눈에 보여주는 요약 이미지입니다.

    9. 정리: 방화벽 설정은 결국 운영 습관입니다

    정리하면 방화벽 설정의 핵심은 세 가지입니다: 기본 차단, 최소 허용, 지속 검증. 사실 특별한 비법은 없습니다. 대신 귀찮아도 반복해야 합니다. 저도 처음엔 규칙 몇 개 넣고 끝내려 했었는데, 시간이 지나 보니 결국 방화벽 보안 체크리스트를 얼마나 성실하게 돌리느냐가 차이를 만들더라고요.

    다음 글에서는 홈랩 기준으로 리버스 프록시(역방향 프록시)와 방화벽을 함께 구성하는 방법도 다뤄볼 예정입니다. 이전 글에서 다뤘던 로그 모니터링 내용과 연결해서 보시면 더 이해가 쉬우실 겁니다.

    자주 묻는 질문

    Q. 방화벽 설정은 서버마다 다르게 해야 하나요?
    네, 서비스 역할이 다르면 달라져야 합니다. 웹 서버, DB 서버, 모니터링 서버는 필요한 포트와 접근 주체가 다르거든요.

    Q. 클라우드 보안 그룹만 있으면 OS 방화벽은 안 써도 되나요?
    환경에 따라 다르지만, 저는 이중으로 두는 편입니다. 방어 계층(다층 방어)이 생기기 때문입니다.

    Q. 제일 먼저 바꿔야 할 한 가지는 뭔가요?
    기본 정책을 정리하고, SSH 같은 관리 포트의 소스 IP 제한부터 거세요. 체감 효과가 가장 큽니다.

    마지막으로 한 줄만 드리면, 방화벽 설정은 한 번 잘해두는 작업이 아니라 계속 점검하는 운영 루�ine입니다. 오늘 서버 한 대라도 체크리스트대로 다시 보시면 분명 놓친 게 하나쯤은 보일 겁니다.

  • [k8s] 쿠버네티스 Secret 관리 베스트 프랙티스: 민감 데이터 보안 강화 전략

    [k8s] 쿠버네티스 Secret 관리 베스트 프랙티스: 민감 데이터 보안 강화 전략

    도입부: 민감 데이터, 이렇게 방치해도 될까요?

    안녕하세요, 13년차 서버실 지킴이입니다. 쿠버네티스(Kubernetes)를 운영하다 보면 정말 많은 난관에 부딪히게 되죠. 그중에서도 민감 데이터(Sensitive Data) 관리는 늘 머리 아픈 숙제였어요. 저도 처음엔 별생각 없이 Secret 리소스를 사용했었는데, 시간이 지날수록 ‘이대로 괜찮을까?’ 하는 불안감이 커지더라고요. 개발자들이 접속 정보, API 키 같은 걸 그냥 Secret에 넣고 쓰는 모습을 보면서 ‘언젠가 터지겠구나’ 싶었거든요.

    실제로 쿠버네티스 환경에서 Secret 관리가 제대로 되지 않아 보안 사고로 이어진 사례도 심심치 않게 들려옵니다. 외부 공격은 물론이고, 내부에서도 불필요한 접근 권한 때문에 문제가 생기기도 하고요. 그래서 오늘은 제가 13년간 인프라 엔지니어로 일하며 겪었던 경험과 홈랩에서 직접 실험해본 것들을 바탕으로, 쿠버네티스 Secret 관리 베스트 프랙티스 체크리스트를 공유해드리려고 합니다. 민감 데이터를 안전하게 보호하기 위한 전략들을 함께 알아볼까요?

    쿠버네티스 클러스터 내 Secret 관리의 중요성을 보여주는 개요 다이어그램

    쿠버네티스 클러스터 내 Secret 관리의 중요성을 보여주는 개요 다이어그램입니다.

    쿠버네티스 Secret, 넌 누구니? (개념 설명)

    먼저, 쿠버네티스 Secret이 정확히 무엇인지부터 짚고 넘어갈게요. 쿠버네티스 Secret(시크릿)은 말 그대로 민감한 정보(Sensitive Information)를 저장하기 위한 오브젝트입니다. 데이터베이스 암호, OAuth 토큰, SSH 키 등을 여기에 저장하고 파드(Pod)에 주입해서 사용하죠. 흔히 환경 변수나 파일 형태로 파드에 마운트(Mount)해서 애플리케이션이 접근하도록 합니다.

    쉽게 말해, 컨테이너 이미지에 직접 민감 정보를 하드코딩(Hard-coding)하거나 YAML 매니페스트에 평문(Plaintext)으로 노출하는 대신, 쿠버네티스 자체적으로 제공하는 저장소를 이용하는 방식이라고 보시면 됩니다. 그런데 여기서 중요한 포인트! 쿠버네티스 Secret은 기본적으로 Base64(베이스64) 인코딩만 되어 있을 뿐, 암호화(Encryption)되어 있지 않습니다. 이 말은 인코딩된 문자열을 누구나 쉽게 디코딩해서 원본 값을 볼 수 있다는 뜻이에요. 이걸 모르고 Secret이 완전히 안전하다고 생각했다간 큰코다칠 수 있습니다.

    Secret 관리, 어떤 점이 문제일까요? (삽질 경험 공유)

    저도 처음엔 ‘그래도 쿠버네티스에서 제공하는 거니까 안전하겠지!’ 하고 막연하게 생각했었어요. 그래서 개발팀에서 요청하는 대로 DB 접속 정보나 외부 API 키를 kubectl create secret generic 명령어로 뚝딱 만들어서 배포했었죠. 그러다가 문득 kubectl get secret <secret-name> -o yaml 명령어를 쳐봤는데, 인코딩된 값들이 너무 쉽게 디코딩되는 걸 보고 깜짝 놀랐습니다. ‘아, 이건 아니구나’ 싶더라고요. 사실 Secret의 가장 큰 문제점은 다음과 같습니다.

    • Base64 인코딩은 암호화가 아니다: 위에서 설명했듯이, 누구나 쉽게 원본 값을 볼 수 있다는 점이 가장 치명적입니다.
    • etcd(엣시디)에 평문 저장 가능성: 쿠버네티스의 모든 오브젝트는 etcd라는 분산 키-값 저장소에 저장됩니다. etcd 자체가 암호화되어 있지 않다면, Secret 내용이 그대로 노출될 수 있습니다.
    • 접근 제어의 복잡성: Secret에 대한 접근 권한을 세밀하게 제어하지 않으면, 불필요한 사용자나 파드가 민감 정보에 접근할 수 있게 됩니다. RBAC(Role-Based Access Control) 설정을 잘못하면 문제가 생기죠.
    • GitOps(깃옵스) 환경과의 충돌: Secret을 Git 리포지토리에 저장하고 싶은데, 평문으로 올릴 수는 없잖아요? 그렇다고 인코딩된 값을 올리는 것도 보안상 좋지 않습니다. 버전 관리와 보안 사이에서 딜레마에 빠지게 됩니다.

    이런 문제점들 때문에 제가 밤늦게까지 홈랩에서 씨름하며 여러 솔루션을 찾아보고 적용해봤었죠. 삽질 좀 했습니다 ㅎㅎ

    민감 데이터 보안 강화 전략 체크리스트 (베스트 프랙티스)

    이제 본격적으로 쿠버네티스 Secret 관리 베스트 프랙티스 체크리스트를 공유해드릴게요. 이 전략들을 하나씩 적용해나가시면 훨씬 안전한 쿠버네티스 환경을 만들 수 있을 겁니다.

    1. etcd 암호화 (Encryption at Rest)

    가장 기본 중의 기본입니다. 쿠버네티스 클러스터의 핵심 데이터 저장소인 etcd에 저장되는 모든 데이터를 암호화해야 합니다. 특히 Secret 오브젝트는 반드시 암호화해야 합니다. 이를 Encryption at Rest(저장 데이터 암호화)라고 부르는데요, kube-apiserver(쿠브-API서버) 설정을 통해 Secret 리소스만 선택적으로 암호화할 수 있습니다.

    2. RBAC(Role-Based Access Control)으로 Secret 접근 제어

    누가 어떤 Secret에 접근할 수 있는지 RBAC를 통해 세밀하게 제어해야 합니다. 최소 권한 원칙(Principle of Least Privilege)을 적용하여, 꼭 필요한 사용자나 파드에게만 필요한 Secret에 대한 읽기 권한을 부여해야 합니다. 예를 들어, 특정 네임스페이스(Namespace)의 파드만 해당 네임스페이스의 Secret을 사용할 수 있도록 제한하는 것이죠.

    3. 외부 Secret 관리 솔루션 활용

    쿠버네티스 기본 Secret의 한계를 보완하기 위해 외부 Secret 관리 솔루션을 적극적으로 고려해보세요. 제가 홈랩에서도 여러 솔루션을 테스트해봤는데, 정말 편하더라고요.

    • HashiCorp Vault(하시코프 볼트): 중앙 집중식 Secret 관리 솔루션의 대명사입니다. 동적 Secret 생성, Secret 리스(Lease), 감사 로그(Audit Log) 등 강력한 기능을 제공합니다. 쿠버네티스와의 연동도 잘 되어 있어서 많은 기업에서 사용하고 있습니다.
    • Sealed Secrets(실드 시크릿): Bitnami에서 개발한 솔루션으로, Secret을 암호화하여 Git 리포지토리에 안전하게 저장할 수 있게 해줍니다. 클러스터 내의 컨트롤러(Controller)가 암호화된 SealedSecret을 복호화하여 일반 Secret으로 만들어줍니다. GitOps 환경에서 특히 유용하죠.
    • 클라우드 제공 Secret Manager: AWS Secrets Manager, Google Secret Manager, Azure Key Vault 등 클라우드 서비스에서 제공하는 Secret 관리 솔루션을 활용하는 것도 좋은 방법입니다.
    쿠버네티스와 외부 Secret 관리 솔루션(Vault, Sealed Secrets) 연동 아키텍처 예시입니다.

    쿠버네티스와 외부 Secret 관리 솔루션(Vault, Sealed Secrets) 연동 아키텍처 예시입니다.

    4. Kubelet Secret 볼륨 암호화 (KMS Provider)

    파드에 마운트(Mount)되는 Secret 볼륨은 tmpfs(임시 파일 시스템)에 저장되지만, 만약 Kubelet(쿠블릿) 노드가 탈취당했을 경우 메모리 덤프 등을 통해 Secret에 접근할 위험이 있습니다. 클라우드 환경에서는 KMS(Key Management Service) Provider를 활용하여 Secret 볼륨을 암호화할 수 있습니다. 예를 들어 AWS EKS나 GCP GKE에서는 KMS를 etcd 암호화뿐만 아니라 Secret 볼륨 암호화에도 활용할 수 있습니다.

    5. Secret 변경 시 애플리케이션 재시작/재배포

    쿠버네티스 Secret은 파드에 환경 변수나 볼륨으로 주입되는데, Secret의 내용이 변경되어도 파드는 자동으로 업데이트된 Secret을 로드하지 않습니다. 즉, 변경 사항을 적용하려면 해당 파드를 재시작(Restart)하거나 재배포(Redeploy)해야 합니다. 이 점을 잊고 ‘왜 Secret 바꿨는데 적용이 안 되지?’ 하고 저처럼 삽질하는 일이 없으시길 바랍니다. Deployment(디플로이먼트)의 Hash(해시) 기반 롤링 업데이트(Rolling Update)를 활용하거나, Reloader 같은 툴을 사용하면 좀 더 자동화할 수 있습니다.

    6. Secret Rotation (정기적 교체)

    아무리 강력하게 암호화하고 접근 제어를 해도, Secret이 영원히 안전하다고 보장할 수는 없습니다. 따라서 Secret을 정기적으로 교체(Rotation)하는 정책을 수립하고 자동화하는 것이 중요합니다. 예를 들어 데이터베이스 암호는 3개월마다, API 키는 6개월마다 교체하는 식이죠. 외부 Secret 관리 솔루션들은 이러한 Secret Rotation 기능을 자체적으로 제공하기도 합니다.

    실전 적용 가이드: etcd 암호화와 Sealed Secrets 예시

    이론만으로는 부족하죠! 제가 직접 적용해봤던 etcd 암호화와 Sealed Secrets의 간단한 예시를 보여드릴게요.

    etcd 암호화 설정

    kube-apiserver 설정을 수정하여 etcd에 저장되는 Secret을 암호화할 수 있습니다. EncryptionConfiguration API를 사용하는데, AES-CBC(고급 암호화 표준-Cipher Block Chaining) 방식이 널리 사용됩니다.

    apiVersion: apiserver.config.k8s.io/v1
    kind: EncryptionConfiguration
    resources:
      - resources:
          - secrets
        providers:
          - aescbc:
              keys:
                - secretbox:
                    secret: <YOUR_AES_KEY_BASE64> # Base64 인코딩된 32바이트 AES 키
          - identity: {}
          - secretbox: {}
    

    여기서 <YOUR_AES_KEY_BASE64>는 직접 생성한 AES 키를 Base64 인코딩한 값입니다. 이 키는 안전하게 보관해야 합니다. 이 설정 파일을 kube-apiserver에 적용하면, 이후 생성되는 Secret들은 모두 etcd에 암호화된 상태로 저장됩니다. 기존 Secret들도 재작성(rewrite)해야 암호화가 적용됩니다.

    Sealed Secrets 도입

    Sealed Secrets는 GitOps 환경에서 Secret을 안전하게 관리하기 위한 좋은 방법입니다. 먼저 클러스터에 Sealed Secrets 컨트롤러를 설치합니다.

    # 컨트롤러 설치 (helm 사용 예시)
    helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
    helm repo update
    helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system
    
    # public key 추출
    kubeseal --fetch-cert > public-cert.pem
    

    그다음, 일반 Secret YAML 파일을 kubeseal CLI 툴을 사용하여 암호화합니다.

    # original-secret.yaml (평문 Secret 예시)
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-app-secret
      namespace: default
    data:
      username: dXNlcg==
      password: cGFzcw==
    type: Opaque
    
    # Secret 암호화
    cat original-secret.yaml | kubeseal --cert public-cert.pem --format yaml > sealed-secret.yaml
    

    이렇게 생성된 sealed-secret.yaml 파일은 암호화되어 Git 리포지토리에 안전하게 저장할 수 있습니다. 클러스터 내의 Sealed Secrets 컨트롤러가 이 파일을 감지하고 자동으로 복호화하여 일반 Secret으로 만들어줍니다.

    Sealed Secrets의 작동 원리를 보여주는 시퀀스 다이어그램입니다.

    Sealed Secrets의 작동 원리를 보여주는 시퀀스 다이어그램입니다.

    제가 겪은 트러블슈팅: 권한 문제와 재배포

    이런 설정들을 적용하다 보면 예상치 못한 문제에 부딪히기 마련이죠. 제가 가장 많이 겪었던 ‘삽질’은 바로 RBAC 권한 문제였습니다. Secret에 대한 접근 권한을 너무 강하게 제한했더니, 정작 애플리케이션 파드가 Secret을 읽지 못해서 배포가 실패하는 경우가 많았어요. 에러 메시지에 permission denied나 secret not found가 뜨면 정말 머리아파죠.

    해결책은 간단했습니다. Role과 RoleBinding을 세밀하게 조정하는 것이죠. 특정 네임스페이스의 ServiceAccount(서비스 계정)에 해당 네임스페이스 내의 Secret에 대한 get, list, watch 권한만 부여하도록 했습니다. 그리고 kubectl auth can-i get secrets --as=system:serviceaccount:<namespace>:<serviceaccount-name> 명령어로 실제 권한을 꼼꼼히 확인하는 습관을 들였어요.

    또 하나는 위에서 언급했던 Secret 변경 후 파드 재배포 문제였습니다. Secret만 바꾸고 파드를 재시작하지 않아서 한참을 헤매다가 결국 kubectl rollout restart deployment <deployment-name> 명령어를 날려야 해결되는 걸 보고 허탈했던 기억이 있네요. 자동화 툴을 사용하기 전까지는 배포 스크립트에 반드시 재시작 로직을 포함시키는 것이 중요합니다.

    마무리하며: 안전한 쿠버네티스 운영을 위한 필수 요소

    오늘은 쿠버네티스 Secret 관리의 중요성과 함께, 제가 직접 겪고 배운 민감 데이터 보안 강화 전략 체크리스트를 공유해드렸습니다. 사실 쿠버네티스 Secret은 그 자체로 완벽한 보안 솔루션이라기보다는, 다른 보안 도구들과 함께 사용될 때 비로소 제 역할을 하는 퍼즐 조각이라고 생각합니다.

    정리하자면:

    1. etcd 암호화는 기본 중의 기본!
    2. RBAC로 Secret 접근 권한을 꼼꼼히 관리하기.
    3. Sealed Secrets나 Vault 같은 외부 솔루션으로 보안 강화 및 GitOps 환경 통합.
    4. KMS Provider를 활용한 Secret 볼륨 암호화 고려.
    5. Secret 변경 시 파드 재시작/재배포 잊지 말기.
    6. Secret Rotation으로 주기적인 보안 강화.

    이 체크리스트를 바탕으로 여러분의 쿠버네티스 환경이 더욱 안전해지기를 바랍니다. 민감 데이터는 언제나 최우선으로 보호해야 할 대상이니까요. 다음 글에서는 특정 외부 Secret 관리 솔루션을 더 깊이 파고드는 내용을 다뤄볼까 합니다. 기대해주세요!

    안전한 쿠버네티스 Secret 관리를 위한 핵심 체크리스트 요약 인포그래픽입니다.

    안전한 쿠버네티스 Secret 관리를 위한 핵심 체크리스트 요약 인포그래픽입니다.