[Docker] Docker로 OpenVPN Server 구축하기 - #3 OpenVPN 서버 실행 및 클라이언트 인증서 생성

    이전 글

    2023.03.15 - [분류 전체보기] - [Docker] Docker로 Ubuntu에 OpenVPN Server 구축하기 #2 OpenVPN 서버 구성


    Generate a client certificate

    VPN 서버측 설정이 준비되었으므로, 이제 접속할 클라이언트의 인증서를 생성해야 한다.

    Client Requirement

    나의 경우는 다음과 같은 요구 사항을 정의해 발급했다.

    1. 클라이언트 OS에 종속되지 않을 것.
    2. 클라이언트 접속 시 비밀번호는 입력하지 않을 것.
    3. 다음과 같이 그룹을 구분해 IP 풀을 정의하고, 이에 해당되는 고정 IP를 할당할 수 있을 것.
      • Group A : 10.95.0.5 ~ 10.95.49.253
      • Group B : 10.95.50.1 ~ 10.95.99.253
      • Group C : 10.95.100.1 ~ 10.95.255.253
    4. 인증서 파일명은 위와 같은 규칙을 반영해 생성할 것.

    요구 사항이 꽤 많고 이를 충족시키려면 무엇이 필요한지 알아본다.

    Support all OS

    클라이언트가 어떤 OS를 사용할 지 모르기 때문에 특정 OS에 종속되지 않고 모든 OS에 대응할 수 있어야 한다.

    * 참고로 모바일의 경우 iOS 및 Android 모두 OpenVPN Client 애플리케이션이 존재하므로 고려하지 않아도 된다.

     

    먼저 모든 OS에 대응하기 위한 힌트는 3번 요구 사항에 있다.

    각 그룹의 호스트 IP가 254가 아닌 253으로 끝나는 것을 볼 수있다.

    이는 아래와 같이 OpenVPN의 'How To' 문서를 읽다 보면 관련된 내용을 찾을 수 있다.

    https://openvpn.net/community-resources/how-to/#configuring-client-specific-rules-and-access-policies

    요약하자면, 나는 개방 네트워크에 접속된 자사 제품 및 장비에 마음대로 접속하기 위해 각 클라이언트 마다 고정 IP를 부여할 것인데, Windows를 사용하는 클라이언트들을 위해 TAP-Windows 드라이버와 호환되도록 가상 IP 주소의 마지막 옥텟에 특별한 값을 지정해야 한다는 것이다.

    여기서 말하는 특별한 값이 위에서 볼 수 있는 주소 쌍(pair)들이다.

     

    예를 들자면, 나는 10.95.0.0/16으로 네트워크를 구성할 것이기에 Windows 클라이언트를 고려하지 않고 차례대로 고정 IP를 부여한다면 다음과 같이 될 것이다.

    • 10.95.0.1
    • 10.95.0.2
    • 10.95.0.3
    • ...
    • 10.95.255.254

    그런데 이러면 Windows 사용자와 호환이 안된다고 하니까 다음과 같이 부여해야 한다.

    • 10.95.0.1
    • 10.95.0.5
    • 10.95.0.9
    • 10.95.0.13
    • ...
    • 10.95.255.249
    • 10.95.255.253

    * 여기서 10.95.0.1은 앞서 서버측을 구성할때 OpenVPN 서버 자체 주소로 사용했으므로 비워둔다.

    이렇게 되면 서브넷 마스크를 24로 두는 IP 주소 풀에서는 가용 호스트가 254개가 아닌 64개가 된다는 것을 알 수 있다.

    No password required

    클라이언트가 접속할 때, 비밀번호를 입력해 인증하는 것이 디폴트다.

    하지만 이를 무시할 수도 있다.

    클라이언트 인증서 생성 시, 해당 인증서는 비밀번호를 필요로 하지 않는다는 의미로 nopass 옵션을 같이 사용하면 된다.

    Grouping

    단순하게 VPN에 접속할 클리아언트를 가상으로 세 그룹으로 분류한 것이다.

    각 그룹의 클라이언트는 물론이고 하나의 그룹에 속하는 클라이언트는 다른 그룹의 클라이언트와도 통신이 가능하다.

    * 그룹화한 IP 주소 풀 각각을 실제 서브넷처럼 사용(subnetting)하려면 추가 스터디가 필요할 것 같다.

    Certificate naming

    클라이언트 인증서를 생성하고 나면 간단한 text editor를 통해 내용을 열어볼 수 있으며 여기서 각각 부여된 고정 IP를 확인할 수 있다.

    하지만 이는 너무 번거로우니 아예 파일 이름에 클라이언트 인증서의 정보를 적어넣는다.

    {group}_OVPN_{fixed_ip_address}.

    Generate Certificate

    위와 같은 요구 사항을 모두 만족시키기 위한 인증서를 생성해본다.

    # Group A
    docker run --rm -v $OVPN_DATA:/etc/openvpn -it kylemanna/openvpn easyrsa build-client-full A_OVPN_10.95.0.5 nopass
    
    # Group B
    docker run --rm -v $OVPN_DATA:/etc/openvpn -it kylemanna/openvpn easyrsa build-client-full B_OVPN_10.95.50.1 nopass
    
    # Group C
    docker run --rm -v $OVPN_DATA:/etc/openvpn -it kylemanna/openvpn easyrsa build-client-full A_OVPN_10.95.100.1 nopass

    인증서 생성 시 기존에 설정한 OpenVPN 서버의 인증 비밀번호를 물어보는데 각자 설정한 비밀번호를 입력한다.

    인증서에 비밀번호를 설정하고 싶다면 nopass 옵션만 없애면 된다.

    Revoke Client

    OpenVPN 서버를 운영하다 보면 생성했던 인증서를 취소해야 하는 경우가 발생할 수도 있다.

    • 개인키/인증서 도난 혹은 분실했을 때
    • 클라이언트 인증서의 비밀번호를 잊어버렸을 때
    • 어떤 이유로 특정 클라이언트의 접근을 종료해야 할 때
    docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient {USER_NAME} remove

    해당 명령어를 사용하면 이전에 서명한 인증서를 무효시켜 더 이상 인증할 수 없게 된다.

     

    Define fixed IP address

    아래 명령어를 입력해 각 클라이언트에게 부여할 고정 IP 주소를 정의한다.

    # Group A
    echo "ifconfig-push 10.95.0.5 10.95.0.6" | docker run -v $OVPN_DATA:/etc/openvpn -i --rm kylemanna/openvpn tee /etc/openvpn/ccd/FCI_OVPN_1_10.95.0.5
    
    # Group B
    echo "ifconfig-push 10.95.50.1 10.95.50.2" | docker run -v $OVPN_DATA:/etc/openvpn -i --rm kylemanna/openvpn tee /etc/openvpn/ccd/FCI_OVPN_1_10.95.50.1
    
    # Group C
    echo "ifconfig-push 10.95.100.1 10.95.100.2" | docker run -v $OVPN_DATA:/etc/openvpn -i --rm kylemanna/openvpn tee /etc/openvpn/ccd/FCI_OVPN_1_10.95.100.1

    예를 들어 클라이언트 FCI_OVPN_1_10.95.50.1 OpenVPN 서버에 접속할 때, 서버는 구성 파일(openvpn.conf)에 명시된 대로 ccd/에서 동일한 이름의 FCI_OVPN_1_10.95.50.1 파일을 찾는다.

    만약 존재한다면 해당 파일에 명시된 IP 주소를 클라이언트에게 부여한다.

    Retrieve client configuration with certificates

    build-client-full 명령어로 생성한 클라이언트 인증서는 아직 컨테이너 내부에 존재하므로 해당 파일을 호스트의 파일 시스템으로 가져와야 한다.

    # Group A
    docker run --rm -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_getclient A_OVPN_10.95.0.5 > $OVPN_DATA/A_OVPN_10.95.0.5
    
    # Group B
    docker run --rm -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_getclient B_OVPN_10.95.50.1 > $OVPN_DATA/B_OVPN_10.95.50.1
    
    # Group C
    docker run --rm -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_getclient C_OVPN_10.95.100.1 > $OVPN_DATA/C_OVPN_10.95.100.1

    이제 초기에 컨테이너를 실행할 때 바인딩한 볼륨 디렉토리에서 클라이언트 설정 파일(.ovpn)을 볼 수 있을 것이다.

    해당 파일을 접속할 클라이언트에게 전달하고 클라이언트는 OpenVPN Connect 애플리케이션을 통해 접속 가능하다.

    https://openvpn.net/vpn-client/

     

    OpenVPN Connect Client | Our Official VPN Client | OpenVPN

    Download the official OpenVPN Connect client software developed and maintained by OpenVPN Inc.

    openvpn.net


    지금까지 다룬 내용은 OpenVPN의 기능들 중에서도 매우 기본적이고 근본적인 기능이다.

    혹시 몰라 나중에 포스팅할 수도 있는, 공부해보고 싶은 고급 기능들을 일단 적어놓아본다.

    • Expanding the scope of the VPN to include additional machines on either the client or server subnet
    • Pushing DHCP options to clients
    • Configuring client-specific rules and access policies
    • How to add dual-factor authentication to an OpenVPN configuration using client-side smart cards
    • Running an OpenVPN server on a dynamic IP address
    • Impelmenting a load-balancing/failover configuration

    댓글

    Designed by JB FACTORY