Iterm2 설정

처음 Mac 을 구매하게 되면 제일 먼저 하는 것이 Iterm2 를 설치하는 것이다. Mac 에서 제공하는 Term 보다 사용하기 편해서 기본적으로 다 설치를 하게 된다. Iterm2 는 테마, 폰트등을 설정할 수 있고 Git 을 이용할 경우에 터미널에서 Branch 상태등을 잘 보여줘서 거의 필수로 설치를 하게된다.

기본상태

Iterm2 를 설치하면 다음과 같다.

프롬프트나 이런것들이 기본상태이다.

oh-my-zsh 설치

oh-my-zsh 는 zsh 에 많은 기능을 부여해준다. 대표적인 것이 Themes, Fonts 등이다. 다음과 같이 설치할 수 있다.

설치를 위와같이 쉘 프롬프트가 변경 된다.

.zshrc

zsh 의 설정은 zshrc 파일에 담겨 있다. 여기에 보면 oh-my-zsh 를 활성화하도록 되어 있으며, 테마등을 설정할 수 있다.

powerlevel10k 테마

여러가지 테마가 있는데, powerlevel10k 테마가 제일 좋아 보인다. 사람마다 성향이 다르기 때문에 어느게 좋다할 수 없지만, 찾아보면 여러가지 테마가 있으니 이것저것 설치하고 변경해보고 하면서 자신에게 맞는 테마를 고르면 된다.

powerlevel10k 는 문답식으로 세팅을 진행하게 된다.

이제, .zshrc 에 ZSH_THEME 를 값을 “powerlevel10k/powerlevel10k” 로 지정한다.

문답설정

zshrc 에 테마를 설정하고 새로운탭으로 터미널을 열면 문답이 진행이 된다.

모든 설정을 하고 나면 위와같이 안내문과 함께 종료 된다.

만일 설정을 다시하고 싶다면 다음과 같이 하면 된다.

Azure Application Gateway 특징

Azure Application Gateway 에 특징이 있는데, 이에 대해 정리한다.

서브넷(Subnet)

Application Gateway 를 위한 전용의 서브넷이 있어야 한다. 서브넷에 다른 서비스가 있다면 선택이 되지 않는다. 예를들어 Subnet1 에 VM 을 생성했다고 하면 Application Gateway 서브넷으로 사용할 수 없다.

따라서 네트워크 설계를 할때에는 Application Gateway 를 위한 전용의 서브넷을 미리 생성을 해야 한다.

Private Subnet 도 가능

Application Geteway 를 생성할때에 Subnet 을 지정하게 된다.

위와같이 Private Subnet 을 지정할 수 있다. 이렇게 지정하고 난후에도 Application Gateway 에 동작하는데에는 아무런 문제가 되지 않는다.

Azure Subnet 에서는 Private Subnet 을 지정하는 옵션이 존재한다. 다음과 같이 설명되어 있다.

Private subnets enhance security by not providing default outbound access. To enable outbound connectivity for virtual machines to access the internet, it is necessary to explicitly grant outbound access. A NAT gateway is the recommended way to provide outbound connectivity for virtual machines in the subnet. 

OutBound Access 에 제한이 걸릴 뿐 Application Gateway 의 동작에는 아무런 문제가 되지 않는다.

Azure Load Balancer

Azure 를 하면서 여러가지 차이점을 느끼지만, 그 중 Azure Load Balancer 만큼 차이를 보여주는 것도 없어보인다. AWS 에서는 Network Load Balancer 에 대응되지만 기능이 몇가지 더 있음으로 해서 아키텍쳐에도 차이를 보인다.

SNAT

Azure LoadBalancer 는 SNAT 기능을 지원한다. Source NAT 라고 하는 것으로 내부 사설IP 를 외부 공인IP 로 변경해 주는 기능이다. 이 기능은 내부 사설망에서 외부 공인 인터넷망으로 통신을 가능하게 해주는 중요한 기능이다.

VM 기반 리소스를 생성할때에 보안상 대부분 사설 서브넷(Private Subnet) 에 위치시킨다. 그리고 서비스를 위해서 VM 앞단에 Load Balancer 를 위치킨다. 문제는 VM 자체적으로 인터넷 통신을 하려고할 때다. 공인IP 가 있다고 하더라도 사설 서브넷에 위치된 VM 은 라우팅으로 인해서 외부로 나갈 수 없어 인터넷 통신을 할 수 없다. AWS 의 경우 이 문제를 해결 하기 위해서 NAT Gateway 서비스를 이용해야 한다.

Azure 에서는 Load Balancer 를 이용하면 이러한 문제를 해결 할 수 있다. 물론 Azure 에서도 NAT Gateway 서비스가 존재하지만 Azure 아케텍쳐상 베스트 프렉티스(Best Practice) 가 아닌 것으로 보인다.

Azure VM 기준 아케텍쳐인데(Azure 공인문서), Frontend 와 Backend 에 위치한 VM들은 모두 사설 서브넷이며 인터넷 통신을 위해서 Load Balancer 를 이용하고 있다. NAT Gateway 를 이용하면 더 좋아 보이는데, 베스트 프렉티스로 되어 있지 않은 모양이다.

Load Balancer 생성

Azure 에 Load Balancer 는 L4 Layer 다. AWS 에 Network Load Balancer 에 대응되지만 SNAT 기능을 제공함으로써 인터넷 통신을 가능하게 해준다.

Load Balancer 생성화면에서 많은 절차가 필요하다는 것을 알수 있는데, Outbound rules 이 SNAT 기능을 사용하는 것이다. 물론 이 기능을 사용하기 위해서는 Inbound rules 설정에서 SNAT 기능을 사용하겠다고 활성화를 해줘야만 한다.

Port allocation

SNAT 설정할때에 문제가 되는 항목이 바로 Port allocation 이다. SNAT 자체가 VM 에서 출발하는 IP 를 변환해주는 것인데, 어쨋거나 Load Balancer 가 대신 공인 인터넷으로 접속을 하게 해주는 것임으로 결국에는 Load Balancer 가 출발지로 되고 결국에는 Client Port 가 있어야 한다.

문제는 VM 에서 인터넷 접속을 이것저것 하게 되면 단 하나의 Client Port 가지고는 되지 않는다. 브라우져를 통해 웹사이트 접속을 하더라도 동시에 몇십게의 Client Port 가 생성된다. 따라서 Load Balancer 입장에서는 뒷단에 있는 VM 들에게 무제한 접속을 허용, 다시 말해서 Client Port 를 할당해 줄수가 없게 된다.

이를 위해서 Azure 는 Port allocation 설정을 하도록 하고 있다. Load Balancer 의 Frontend IP 당 뒷단 VM 수를 조합해 VM 하나에 할당가능한 Port 의 개수를 정하도록 해 놨다.

Port allocation 의 방식을 Manually 로 하지 않고, Azure 에 위임할 경우에 Scale out 시에 뒷단 VM 의 연결이 안될 수도 있다. 위와같이 수동으로 하고 뒷단 인스턴스 개수를 지정해주는 것을 권장하고 있다.

이 설정을 하게되면 SNAT 설정이 완료된다. 이제 VM 에서 인터넷이 되는지 확인해보면 된다.

DNAT

Azure Load Balancer 는 DNAT 기능을 제공한다. 이 기능일 이용하면 Load Balancer 뒷단 VM 에 접속을 할 수 있다. 하지만 이 기능은 잘 사용하지 않는 것으로 보인다. 베스트 프렉티스 아키텍쳐에서는 Bastion 서버를 구성해서 사용하는 것으로 보이는데, 어쨌든 DNAT 기능을 제공한다.

SNAT 기능은 Outbound rule 이라고 한다면 DNAT 는 Inbound NAT rule 이라고 한다.

테스트를 위해서 SSH(22 port) 를 활성해서 뒷단 VM 에 접속하도록 했다. 이렇게 되면 Load Balancer 의 공인IP 를 기반으로 VM 에 22 포트로 접속이 가능해 진다. Frontend Port 의 경우에는 잘 알려진 포트가 아닌 다른 포트를 이용하는 것이 좋다.

결론

Azure Load Balancer 는 L4 Layer 장비다. AWS 와 달리 SNAT, DNAT 기능을 모두 지원함으로써 뒷단 VM 에 특정한 기능을 제공한다.

Azure 기술 문서에는 사설 서브넷에 위치한 VM 의 인터넷 연결을 위해서 Load Balancer 를 이용하고 있다. VM 접속을 위해서는 Bastion 서비스를 이용하도록 구성하고 있어서 Inbound NAT Rule 은 임시적으로 긴급한 상황이 아니라면 크게 사용할 일은 없어보인다.

Ingress-Nginx 설치

Kubernetes 에서 인기있는 Ingress Controller 로 Nginx 가 있다. 설치는 Helm 을 이용하면 된다.

설치 명령어를 보면, 여러가지 파라메터가 보이는데 kube-prometheus-stack 으로 설치한 prometheus 까지 고려한 것이다.

관련 명령어나 파라메터는 다음의 주소에 매우 잘 설명되어 있어서 별도로 추가설명은 하지 않는다.

쿠버네티스 prometheus 설정

Helm 을 이용해 kube-prometheus-stack 을 설치하게 되면, Grafana 를 통해서 통계 그래프를 볼 수 있다. 그런데, 몇몇 대쉬보드는 나타나지 않는데 여기서는 이 문제를 해결하는 방법을 알아본다.

Prometheus

프로메테스에서 Status > Target health 에서 상태를 같이 보면서 해결하면 좋다. 어떻게 스크랩이 설정되어 있는데, 상태가 DOWN 인 부분을 잘 살펴보면 된다.

CoreDNS

CoreDNS 대쉬보드가 아무것도 나오지 않는다. Service 에 kube-dns 혹은 Helm 으로 설치할 경우에 coredns 로 나오는데, describe 를 한번 해본다.

위에 내용을 보면 k8s-app=coredns 가 보인다. 이제 Service 에 prometheus-coredns 를 한번 보자.

Selector 를 보면 k8s-app=kube-dns 로 보인다. 이것이 맞지 않아서 관련 내용을 가지고 오지 못하는 원인다. 이것을 k8s-app=coredns 로 바꿔 준다.

이렇게 하고 Prometheus 에 Status > Target health 에서 coredns 를 보면 스크랩이 잘되는 것으로 바뀐다.

Etcd

Prometheus 에서 Status > Target health 에서 ‘http://192.168.96.60:2381/metrics‘ 로 EndPoint 로 설정되어 있다. curl 로 긁어보면 다음과 같이 나온다.

Etcd 의 경우에는 상태 모니터링을 위한 파라메터 설정을 해줘야 한다. 하지만 kubeadm 으로 K8S 를 설치한 경우에 etcd 는 Master Controll Plane 으로 동작하기 때문에 파라메터 수정을 위해서는 manifest 파일을 수정으로 해야 한다.

2381 포트를 보면, 127.0.0.1 만 엔드포인트로 되어 있다. 192.168.96.60 을 추가해 준다. 그러면 정상화 된다.

Controller Manager

Prometheus 에서 Status > Target health 에서 ‘dial tcp 192.168.96.60:10257: connect: connection refused’ 에러 메시지가 나타난다.

Controller Manager 또한 Master Controller Plane 이기 때문에 manifest 파일을 수정해줘야 한다.

bind-address 주소가 localhost 로 되어 있기 때문에 refused 된 것으로 보인다. 0.0.0.0 으로 바꾼다.

kube-scheduler

kube-scheduler 도 위에 controller manager 처럼 bind-address 가 localhost 로 되어 있다. 0.0.0.0 으로 바꾼다.

kube-proxy

kube-proxy 는 DaemonSet 오브젝트다. 설정 파일이 있는 것처럼 나오지만 설정파일은 없고, 대신 ConfigMap 으로 존재한다. 이 ConfigMap 에 metricsBindAddress 값이 없다. 이 값을 0.0.0.0 으로 지정해 준다.

DaemonSet 은 자동으로 재시작되지 않는다. Rollout 업데이트를 해준다.

kube-prometheus-stack 설치

기존에 prometheus 설치를 했었는데, 버전을 올릴겸해서 다시 설치를 했다. 설치는 Helm 을 이용했고, 기존에 설치된 버전을 삭제 처리 했다.

환경

K8S 환경이 매우 중요하다. 필자의 환경은 Handy way 방법으로 설치를 진행한 상황이기 때문에 etcd, apiserver, scheduler 가 OS 데몬으로 운영되고 있다. 따라서 Master, Worker 노드의 IP 를 필요로 한다.

만일 kubeadm 으로 설치했다면 selector 를 이용해서 라벨을 선택해주면 된다.

삭제

Helm 을 이용해서 설치했기 때문에 Helm 으로 삭제를 해야 한다. 여기서 한가지 주의해야 하는 것이 있는데, Helm 으로 삭제를 하여도 CRD(Custom Resource Definition) 은 삭제되지 않기 때문에 수동으로 삭제를 해줘야 한다.

남아 있는 crd 가 다를 수가 있지만, 반드시 삭제를 해줘야 문제가 발생하지 않는다. crd 는 다른 프로그램에서도 삭제가 되지 않는 경우가 많다.

Helm repo update

Helm 저장소를 업데이트를 해야 한다.

Download a chart and untar

Helm Chart 를 다운로드하고 압축해제 한다. 이렇게 함으로써 values.yaml 파일을 수정할 수 있게된다.

다운로드와 함께 압축을 해제해 준다.

Values.yaml 파일 수정

어떤 내용들을 수정할지는 어떤 것을 모니터링 할지, 어떤 부분이 있는지에 따라서 달라진다. 변경된 내용은 대략 다음과 같다.

nodeSelector 에 system.rule: monitoring 이 보이는데, 이는 Worker 노드에 라벨을 말한다. 선택된 라벨을 가지고 있는 Worker 노드에 Prometheus 가 설치된다. 단, 이것도 상황에 따라서 달라지는데 Node exporter 의 경우에는 각 노드에 설치가 되어야 하기 때문에 라벨을 설정하지 않는다.

Node 라벨 생성

system.rule: monitoring 이라는 라벨을 생성해야 한다.

이렇게 하면 kworker3 에 prometheus 가 설치된다.

Dependency Update

Helm 을 이용해서 설치해야 한다. 그전에 kube-prometheus-stack 에 의존성이 있는 패키지를 업데이트 해줘야 한다.

설치

Helm 을 이용해 수정한 values.yaml 을 가지고 설치를 한다.

설치가 완료 되면 Pod, Service 에 Prometheus 가 올라오게 된다.

K8S dnstools 사용하기

K8S 를 사용하다보면 여러가지 검증을 위해 Pod 를 필요로 하는 경우가 있는데, dnstools 이 유용하다. 다음과 같이 사용할 수 있다.

Pod 가 생성되면서 dnstools 컨테이너에 진입하게 되고 exit 를 하게 되면 Pod 는 삭제된다.

혹은 curl 이미지를 이용하는 방법도 있다.

Metallb v0.14.9 설치

과거 Metallb 의 버전이 0.10 이였고 K8S 버전도 1.32 이여서 최신 버전으로 다시 설치를 해봤다.

환경

K8S 환경에서 설치를 하지만 CNI 등을 고려해 설치를 진행해야 한다. 내가 설치한 환경은 좀 더 특이한데, K8S 를 Hand Way 방법으로 설치한 상태다. Hand Way 로 설치를 하게 되면 Kube-apiserver, controller, kubelet, kube-scheduler, kube-proxy 같은 것을 컨테이너 방법이 아닌 OS 프로그램 방법으로 설치를 하게 된다. K8S 에서 사용하는 인증서도 수동으로 해줘야 한다.

요약하면 다음과 같다.

  • K8S 설치: Handy way
  • K8S Version: 1.32.2
  • Containerd: 1.7.26
  • CNI: Calico

다운로드

다운로드는 CURL 이나 WGET 명령어를 이용하면 된다.

설치 문서를 보면 이 manifest 파일로 설치가 가능하다고 하지만 여러가지 환경으로 인해서 추가로 파일을 작성해야할 필요도 있다.

metallb 설치

다운로드 받은 metallb-native.yaml 파일을 적용해 설치해 준다.

설치는 아무런 문제 없이 모두 잘 설치가 된다.

IPAddressPool 생성

Metallb 에서 사용할 고정IP 대역을 Pool 로 가지고 있어야 하는데, 이것을 생성해 줘야 한다.

위와 같은 addresses 를 할당해 준다. 필자는 집에서 K8S 를 구축했기 때문에 Private IP 대역을 할당해 줬다.

생성을 위해서 파일을 적용해 주면 위와같은 오류가 발생하게 된다.

이러한 오류는 validatingwebhookconfiguration 에 metallb-webhook-configuration 설정에서 문제가 된다. Webhook 이 필요한 것인데, 이에 대한 추가적인 설정을 해줘도 되지만 일단 삭제하는 것으로 처리 한다.

이렇게 한 후에 다시 metallb-ipaddress.yaml 파일을 적용하면 잘 된다.

L2 mode

필자의 경우에는 L2 mode 로 작동되도록 해야 한다. BGP 도 있기는 하지만, 필자의 경우에는 상관 없는 것이기 때문에 L2 mode 를 위해서 다음과 같이 manifest 파일을 작성한다.

metallb-L2Advertisement.yaml 파일을 적용한다.

LoadBalancer 타입 변경

이제 고정 IP 를 필요로 하는 Service 에 타입을 ClusterIP 에서 LoadBalancer 로 변경해 본다. Metallb 설치가 정상적이라면 다음과 같이 된다.

EXTERNAL-IP 에 Metallb 의 IPAddresses Pool 중에 하나의 IP가 할당된다.

그리고 describe 결과는 다음과 같다.

EndPoints 는 Nodes IP가 보이고 Port 도 할당된게 보인다. 이건 아마도 Hand Way 설치로 인한 것으로 보인다. 원래 kubeadm 으로 설치를 하게 될 경우에 Node IP 조차도 K8S IP 여야 하는데, 여기서는 Node IP 자체가 OS 자체에 할당된 IP로 나타난다.

AWS EC2 에 OpenVPN 서버 구축

리눅스에서 OpenVPN 서버 구축해 보도록 한다. 리눅스 서버는 Ubuntu 24.04 LTS 이다.

아키텍쳐

현재 AWS 아키텍쳐는 다음과 같다.

OpenVPN 를 설치할 서버는 AWS 에 Public Subnet 에 있으며 외부에서 접속을 위해서 EIP(Elastic IP) 를 할당 해줬다. VPC 내에 모든 서버들은 172.31.0.0/16 대역폭에 자동으로 IP를 할당받아 Private IP 를 구성하도록 되어 있다.

이제 사내망 PC 에서 server1 에 Private IP 로 접속을 하기 위한 방법으로 OpenVPN 서버를 설치해보도록 한다.

OpenVPN 작동 방식

OpenVPN 의 작동방법은 NAT 기능을 이용하는 것이다. 먼저, OpenVPN 서버를 설치하고 기동하면 OpenVPN 서버는 서버에 tun0 라고 하는 네트워크 인터페이스 생성한다. 물론 이렇게 생성한 NIC에 네트워크 서브넷을 할당한다. tun0 에 IP를 할당하고 서브넷 라우팅도 함께 구성하게 된다.

이제 OpenVPN 클라이언트를 설치하고 설정파일을 읽어 연결을 하게 되면, OpenVPN 클라이언트는 PC 에 tap0 라고 하는 네트워크 인터페이스를 생성한다. 그리고 이 tap0 에는 OpenVPN 서버로부터 네트워크 관련 정보를 전달 받아서 tun0 와 동일네트워크에 IP, Defaut GW 를 구성하게 된다. 이를 다이어그램으로 표현하면 다음과 같다.

OpenVPN 을 이용하는 이유는 172.31.0.0/16 대역에 있는 서버에 접속하기 위해서다. AWS 아키텍쳐 그림상 server1 에 사내PC가 직접 접속할 방법이 없다. 하지만 OpenVPN 을 이용하면 가능하다. 다음과 같이 접속이 이루어진다.

사내PC(192.168.96.112.66) -> tap(192.168.200.56) —– 인터넷 —–> OpenVPN 서버 tun0(192.168.96.200.1) — NAT –> server1(172.31.0.43)

이러한 흐름을 보면 OpenVPN 서버의 설정에서 OpenVPN 서버와 Client 연결을 위한 네트워크 대역 할당과 server1 의 접속은 OpenVPN 서버를 거쳐서 와야하기 때문에 AWS VPC 네트워크 대역을 알려줘야 하고 OpenVPN 서버는 NAT 서버로 동작해야 한다는(그래서 iptables 을 이용한 MASQUERADE 설정을 한다.) 걸 알게 된다.

OpenVPN 2.6

현 시점에서 OpenVPN 은 2.5 를 기준으로 구분이 된다. 2.6 은 현재 최신 버전으로 사용되고 있는데, 2.5 를 기준으로해서 설정에 많은 변화가 있음으로 만일 처음 구축한다면 2.6으로 하고 호환성을 고려한다면 2.4 를 기준으로 구축하는 걸 권장 한다.

OpenVPN 설치

설치는 Ubuntu 24.04 LTS 에서 기본으로 제공하는 패키지로 설치가 가능하다. 이때 OpenVPN 이 사용할 인증서 생성을 위해서 easy-rsa 명령어도 함께 설치해야 한다.

인증서 생성

OpenVPN 서버는 Client 와 보안통신을 위해서 인증서를 필요로 한다. 인증서를 만드는 것은 그렇게 쉬운 절차가 아니여서 많은 이들이 어려움을 겪는데, easy-rsa 를 이용하면 비교적 쉽게 만들 수 있다.

인증서는 서버 인증서와 클라이언트 인증서가 필요하고 이 둘의 인증서를 만들기 위한 CA 인증서도 있어야 한다.

easy-rsa 명령어만 이용하는게 아니라 디렉토리도 있어야 하는데 /usr/share/easy-rsa/3 에서 작업해야 한다.(중요)

easyrsa 초기화

먼저 easyrsa 를 초기화 해준다. /usr/share/easy-rsa 디렉토리로 이동한다. 여기서 다음과 같이 vars 파일을 만든다.

이 파일은 CSR 내용이기 때문에 상황에 맞게 입력해주면 된다. 그리고 다음과 같이 easy-rsa 를 초기화 한다.

CA 인증서 제작

다음과 같이 root CA 인증서를 제작한다.

root CA 인증서가 생성되었다.

서버 인증서

서버 인증서를 만든다. 서버 인증서를 만들기 위해서는 도메인이 필요하다. 이 도메인은 반드시 있어야 하는건 아니고 서버-클라이언트간 보안을 위한 검증을 위한 것으로 가상으로 입력해줘도 된다.

openvpn.systemv.pe.kr 도메인은 가상으로 그냥 적은 것이다. 굳이 신경쓸 필요는 없다.

클라이언트 인증서 제작

여기서 특징이 있는데, OpenVPN 을 위한 Client 인증서는 사용자마다 제작을 해줘야 한다. 그래서 Client 이름은 ID나 이메일등을 지정해 주면 된다.

Diffie-Hellman key 생성

서버 접속을 위한 Diffie-Hellman key 를 다음과 같이 생성해 준다.

TLS-Auth key 인증 키 생성

다음과 같이 TLS-Auth 키를 생성해 준다.

생성한 키 복사

이렇게 생성한 키들을 OpenVPN 서버에 설정 디렉토리에 복사해 준다. 여기서 주의해야 할것이 배포판마다 설정 디렉토리가 다를 수 있다. Ubuntu24.04 LTS 의 경우에 /etc/openvpn 디렉토리다.

OpenVPN 서버 설정

이제 필요한 파일을 모두 갖췄으니, OpenVPN 설정을 해야 한다. 설정을 어떻게 해야할지 모르기 때문에 OpenVPN 에서 제공하는 Sample 파일을 이용해서 해보자.

이제 server.conf 파일을 다음과 같이 설정해준다.

여기서 AWS VPC CIDR 과 OpenVPN CIDR, DNS 서버 설정등을 주의해서 봐야 한다.

iptables 설정

테스트 하는 서버에는 ufw 명령어가 없다. 만일 ufw 명령어가 있다면 이것을 이용하는 방법으로 해야한다.

iptables 설정을 하는 이유는 MASQUERADE 때문이다. OpenVPN 서버가 NAT로 작동하기 위해서 Iptables 을 이용해 패킷의 흐름을 제어해야 하기 때문이다.

여기서 또 한가지, OpenVPN 서버가 실행중일 때에만 MASQUERADE 설정을 유지하고 실행하지 않을때에는 설정을 꺼야 한다. Iptables 초기화를 하면 설정이 초기화 된다. 이를 위해서 Iptables 설정과 해제 두개의 파일을 작성한다.

먼저 add-bridge.sh 라는 이름으로 쉘 스크립트를 다음과 같이 만든다.

내용이 많지만, 맨 아래 두줄이 핵심이다. tun0 네트워크 장치로부터 192.168.200.0/24 대역으로 들어온 IP에 대해서 enX0 장치를 이용해 172.31.0.0/16 대역으로 패킷을 포워딩 하고 MASQUERADE 설정을 해주고 있다.

OpenVPN 서버가 정지하면 초기화 해주는 remove-bridge.sh 파일을 만들어 준다.

모든 체인을 플러쉬하고 POSTROUTING 룰을 삭제한다.

이렇게 만들어진 파일을 systemd unit 파일인 openvpn@server 에 override 설정으로 추가해준다. override 설정은 파일을 일반 편집으로 해서 추가해주면 자동으로 알아서 추가가 된다.

이렇게 하면 openvpn 시작/중지 때마다 쉘 스크립트가 실행 된다.

시작/중지

이제 시작과 중지를 해보자. 다음과 같이 한다.

OpenVPN 클라이언트 설정

OpenVPN 홈페이지에서 Windows 용 클라이언트를 다운받아 설치한다. 설정 파일은 개인마다 가지고 있어야 해서 전체 시스템에 액세스하는 디렉토리에 넣으면 좋지 않다. 이는 설치가 끝나면 팝업으로 알려주는데, C:\Users\계정ID\OpenVPN\config 이다.

이 디렉토리에 서버에서 작성한 파일을 복사해줘야 한다. 복사해야 할 파일은 다음과 같다.

  • linux.crt (클라이언트 인증서)
  • linux.key (클라이언트 인증서 암호화 키)
  • ca.crt (CA 인증서)
  • ta.key (TLS-Auth Key)

이제 linux.ovpn 파일을 다음과 같이 작성한다.

위와같이 작성하고 OpenVPN Client 에서 설정 파일을 지정하고 연결하기 하면 연결이 된다.

Self Signed 인증서 만들기

이 포스팅은 Self Signed 인증서 만들기 간략한 버전이다. 이론적인 내용은 빼고 OpenSSL 을 이용해서 만드는 방법을 설명한다.

만들기 순서

Self Signed 인증서 만들때에는 순서가 있다.

  1. root CA 를 위한 비밀키 생성(비대칭키)
  2. root 인증서 생성 위한 CSR 생성
  3. root 인증서 생성
  4. Server 인증서를 위한 비밀키 생성(비대칭키)
  5. Server 인증서 생성을 위한 CSR 생성
  6. Server 인증서 생성

대략 위와 같은 순서를 따른다. 비대칭 비밀키를 생성을 위해서 openssl 명령어를 사용한다. 글의 진행을 위해서 a.com 도메인에 대한 인증서를 생성하는 것으로 가정한다.

v3 확장

한가지 알고 가야할 것이 x509 표준에 v3 확장이다. 이 확장은 인증서에 대한 버전을 말하는 것으로 현재 Version 3 에서 확장(Extend) 된 것을 말한다.

v3 확장을 이용하면 SAN(Subject Alternative Name) 을 포함한 인증서를 생성할 수 있다.

이러한 확장을 이용하기 위해서 일종의 명세서 파일을 이용하게 되는데, 인증서 생성에 있어서 이 명세서 파일이 핵심이라고 할 수 있다. CSR 및 인증서 생성에 명세서 파일이 사용된다고 할 수 있다.

root CA 를 위한 비밀키 생성

openssl 를 이용해서 root CA 를 위한 비밀키를 다음과 같이 생성한다.

비밀키가 정상적으로 생성이 된다. 생성된 비밀키에 대한 정보는 다음의 명령어로 확인이 가능하다.

참고로 비밀키를 이용해서 공개키(Public Key) 를 생성할 수 있는데, 다음과 같다.

root 인증서 생성 위한 CSR 생성

CSR 파일을 생성하기 명세서 파일을 이용한다. 명세서 파일은 CSR 만 아니라 인증서 생성에도 사용된다. 명세서 파일을 rootCA.cnf 이름으로 생성한다.

위 명세서는 아무렇게나 만는게 아니며 정해진 규칙이 있다. dn 섹션에는 CSR 작성시 입력할 인증서에 대한 요청자 정보를 입력하는 필드를 지정할 수 있다.

이제 RootCA.cnf 명세서 파일을 이용해서 CSR 파일을 다음과 같이 작성한다.

명세서에 dn 섹션에 내용을 출력하고 있다. CSR 파일이 생성이 되었다.

root 인증서 생성

이제 지금까지 생성된 비밀키와 CSR 파일을 이용해 인증서를 생성한다. 인증서를 생성할때에는 인증서의 사용기간을 정해야 한다.

인증서의 사용기간은 730 일이다. 그리고 -extensions v3_ca 를 인자로 줬는데, 명세서 파일인 RootCA.cnf 파일에 v3_ca 섹션을 사용하라는 뜻이다. v3_ca 섹션에는 인증서에 대한 사용범위, RootCA 임을 증명하는 CA:TRUE 등이 있다.

확인은 다음과 같이 할 수 있다.

Server 인증서를 위한 비밀키 생성(비대칭키)

이제 서버 인증서를 생성해야 한다. 서버 인증서를 위한 비밀키를 다음과 같이 생성한다.

Server 인증서 생성을 위한 CSR 생성

이제 서버 인증서 생성을 위한 명세서 파일을 server.cnf 파일 이름으로 다음과 같이 생성 한다.

RootCA 인증서와 차이점이 보인다. alt_names 섹션이 추가 되었다. 그리고 CA:FALSE 이며 keyUsage 도 다르다. 이 명세서를 이용해서 서버인증서를 위한 CSR 를 생성한다.

예제를 위해서 CSR 입력 내용이 RootCA 와 동일하지만 공인 인증서는 서버CSR 입력 내용이 RootCA 와 같을 수가 없다.

Server 인증서 생성

이제 Server 비밀키와 CSR, RootCA 인증서, RootCA 비밀키를 이용해서 Server 인증서를 생성한다.

생성된 인증서를 확인해 보면 CA:FALSE 로 나타나고, Subject Alternative Name 이 명세서에 내용과 같다.

PKCS12 포맷 인증서 변경

PKCS12 포맷은 Java 시스템에서 사용하는 인증서 포맷이다. 앞서 생성한 인증서는 PEM 포맷 인증서라서 Java 시스템에서 바로 이용할 수 없다. PEM 파일이 있다면 PCKS 포맷 인증서로 변경이 가능하다.

-name 은 Alias Name 을 말한다. 패스워드를 지정하지 않을려면 입력하지 않고 엔터만 치면 된다.

제대로 되었는지 다음과 같이 확인할 수 있다.

SpringBoot 에서는 다음과 같이 application.properties 에 다음과 같이 사용할 수 있다.