docker를 이용한 openVPN 설정

컨테이너가 아닌 네이티브 설치는 다음 포스트를 참조
openVPN 서버구축 #1. 개요
openVPN 서버구축 #2. 서버 설치 및 설정

docker-compose.yaml 생성

version: '2'
services:
  openvpn:
    cap_add:
     - NET_ADMIN
    image: kylemanna/openvpn
    container_name: openvpn
    ports:
     - "1194:1194/udp" 
    restart: always
    volumes:
     - ./openvpn-data/conf:/etc/openvpn #.openvpn-data/conf 디렉토리를 생성해야 한다.

설정파일 및 인증서 초기화

docker-compose run --rm openvpn ovpn_genconfig -u udp://VPN.YOUR_HOST.NAME

# 아래는 수행 결과
reating network "vpn_default" with the default driver
Pulling openvpn (kylemanna/openvpn:)...
....중략....
Creating vpn_openvpn_run ... done
Processing PUSH Config: 'block-outside-dns'
Processing Route Config: '192.168.254.0/24'
Processing PUSH Config: 'dhcp-option DNS 8.8.8.8'
Processing PUSH Config: 'dhcp-option DNS 8.8.4.4'
Processing PUSH Config: 'comp-lzo no'
Successfully generated config
Cleaning up before Exit ...
docker-compose run --rm openvpn ovpn_initpki

# 아래는 수행 결과
Creating vpn_openvpn_run ... done

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/pki

Using SSL: openssl OpenSSL 1.1.1g  21 Apr 2020

Enter New CA Key Passphrase: CA_KEY의_Passphrase
Re-Enter New CA Key Passphrase: CA_KEY의_Passphrase
Generating RSA private key, 2048 bit long modulus (2 primes)
................................+++++
......................................................+++++
e is 65537 (0x010001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:vpn.haedongg.net

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/pki/ca.crt

Using SSL: openssl OpenSSL 1.1.1g  21 Apr 2020
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
..............................................................+...........................................+..........................................................
...중략...
........................................................+..+....................+................................................................+....+..++*++*++*++*

DH parameters of size 2048 created at /etc/openvpn/pki/dh.pem

Using SSL: openssl OpenSSL 1.1.1g  21 Apr 2020
Generating a RSA private key
.............+++++
............................+++++
writing new private key to '/etc/openvpn/pki/easy-rsa-74.akeLei/tmp.JBdIKe'
-----
Using configuration from /etc/openvpn/pki/easy-rsa-74.akeLei/tmp.BfJlok
Enter pass phrase for /etc/openvpn/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'vpn.haedongg.net'
Certificate is to be certified until Jul 30 00:51:51 2025 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Using SSL: openssl OpenSSL 1.1.1g  21 Apr 2020
Using configuration from /etc/openvpn/pki/easy-rsa-149.FPcifA/tmp.cjaMHC
Enter pass phrase for /etc/openvpn/pki/private/ca.key: 위_11_12_라인에서_입력했던_Passphrase

An updated CRL has been created.
CRL file: /etc/openvpn/pki/crl.pem

디렉토리 권한 변경

sudo chown -R $(whoami): ./openvpn-data

서버 프로세스 실행

docker-compose up -d openvpn

클라이언트 사용자 생성 및 인증서 생성

# 비밀번호화 함께 생성
docker-compose run --rm openvpn easyrsa build-client-full 사용자_이름

# 비밀번호 없이 생성
docker-compose run --rm openvpn easyrsa build-client-full 사용자_이름 nopass

# 인증서 파일 출력, 이 파일을 클라이언트 사용자에게 전달하면 된다.
docker-compose run --rm openvpn ovpn_getclient 사용자_이름 > 사용자_이름.ovpn

클라이언트 사용자 제거

# Keep the corresponding crt, key and req files.
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME

# Remove the corresponding crt, key and req files.
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME remove

WBS 양식

WBS란 업무 분업 구조(work-breakdown structure, WBS), 작업 분해 구조, 작업 분류 체계, 작업 분할 구조, 작업 분할 구도는 프로젝트 관리와 시스템 공학 분야에서 프로젝트의 더 작은 요소로 분해시킨 딜리버러블 지향 분업 구조이다. 업무 분업 구조는 팀의 작업을 관리 가능한 부분들로 조직화해놓은 주된 제품 딜리버러블이다. 프로젝트 관리 지식 체계 (PMBOK 5)는 업무 분업 구조를 “프로젝트 팀이 프로젝트 목표를 달성하고 필요한 딜리버러블을 만들기 위한 총 업무 범위의 계층적 분해”로 정의한다업무 분업 구조(work-breakdown structure, WBS)[2], 작업 분해 구조, 작업 분류 체계, 작업 분할 구조, 작업 분할 구도는 프로젝트 관리와 시스템 공학 분야에서 프로젝트의 더 작은 요소로 분해시킨 딜리버러블 지향 분업 구조이다. 업무 분업 구조는 팀의 작업을 관리 가능한 부분들로 조직화해놓은 주된 제품 딜리버러블이다. 프로젝트 관리 지식 체계 (PMBOK 5)는 업무 분업 구조를 “프로젝트 팀이 프로젝트 목표를 달성하고 필요한 딜리버러블을 만들기 위한 총 업무 범위의 계층적 분해”로 정의한다.

첨부된 파일은 일반적으로 많이 활용하는 형태의 WBS 양식일 뿐으로 각 회사 또는 각 업무 담당자(프로젝트 매니저)에 따라 별도로 WBS를 작성하여 관리하는 경우가 많으므로 참고 용도로만 활용하도록 하자

docker image에 ssh 서비스 추가 (멀티 서비스 띄우기)

docker 컨테이너는 마지막 CMD 혹은 ENTRYPOINT 명령 하나로 컨테이너를 시작한다.
즉, 아래와 같이 docker file을 생성해도 ssh와 httpd가 모두 실행되지 않는다는 이야기이다.

...전략...
# ssh 시작
CMD ["/usr/sbin/sshd", "-D"]
# httpd 시작
CMD ["/usr/local/apache2/bin/httpd", "-DFOREGROUND"]

하지만 편의상 컨테이너에 ssh로 접속하고, 이를 통해 컨테이너 내부 상황을 확인하거나 하고 싶다면 ssh를 추가해줘야 한다.
이를 위해 실행할 서비스만큼 스크립트를 생성하고 wrapper 스크립트를 만들어서 이들을 실행해줘야 한다. 아래 스크립트와 dockerfile을 참고해서 이미지를 만들면 된다.

## ssh를 실행하기 위한 스크립트 
## ssh_start.sh
#!/bin/bash
/usr/sbin/sshd -D

## apache를 실행하기 위한 스크립트
## httpd_start.sh
#!/bin/bash
/usr/local/apache2/bin/httpd -DFOREGROUND

## wrapper script
## wrapper.sh
#!/bin/bash
set -m
/ssh_start.sh &
/httpd_start.sh &
fg %1
## dockerfile 예시
## httpd 이미지에 ssh를 추가하여 연결하고 싶은 경우에 대한 예시
# base가 될 이미지
FROM httpd

#아래 작업들을 수행할 계정 (apt 등은 root 권한이 필요하다)
USER root

ENV DEBIAN_FRONTEND=noninteractive \
    TZ=Asia/Seoul

# ssh server 설치
### Ubuntu
RUN apt-get update                                            &&\
    apt-get install -y openssh-server                         &&\
    apt-get install -y curl vi vim tcpdump net-tools          &&\  #필요한 경우 설치한다.
    apt-get clean                                             &&\
    rm -rf /var/lib/apt/lists/*    /tmp/*    /var/tmp/*

RUN mkdir /var/run/sshd
RUN echo 'root:password' | chpasswd
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
RUN sed -i 's/#X11Forwarding no/X11Forwarding yes/' /etc/ssh/sshd_config
RUN echo "export VISIBLE=now" >> /etc/profile


# 사용자 추가
RUN useradd haedong -G sudo -m -d /home/haedong -s /bin/bash
RUN echo 'haedong:password'| chpasswd
RUN echo alias "ls='ls --color=auto'" >> ~/.bash_profile
RUN echo alias "ll='ls -lha" >> ~/.bash_profile

RUN mkdir /var/run/sshd

# 외부로 연결할 포트
EXPOSE 22 80

# 서비스 시작을 위한 스크립트
RUN mkdir -p /root/scripts
COPY ssh_start.sh /root/scripts/ssh_start.sh
COPY httpd_start.sh /root/scripts/httpd_start.sh
COPY wrapper.sh /root/scripts/wrapper.sh

CMD /root/scripts/wrapper.sh

컨테이너 빌드 및 시작

# image build
docker build -t httpd:new .

# 컨테이너 시작
docker run -d -p 2222:20 -p 8888:80 httpd:new