일상의 정리

'전체 글'에 해당되는 글 62건

  1. Orange pi를 이용한 IKEv2 VPN Server 설치 6
  2. Notepad++ 64bit Hex Editor 플러그인 설치 1
  3. CMake 플랫폼 체크하기

Orange pi를 이용한 IKEv2 VPN Server 설치

리눅스/설치

VPN 서비스는 외국에서 한국의 서비스를 이용하거나, mVOIP 사용량 제한을 우회하기 위해 많이 사용됩니다.
이번에 
중국에 지인이 있어서 중국의 만리 방화벽을 뚫을 수 있는 VPN 서비스를 찾다 보니 일반 공유기가 지원하는 L2TP 또는 PPTP등의 VPN 서비스는 만리 방화벽에 막혀서 안된다고 합니다. 그래서 가능한 방법을 찾아보니 IKEv2 VPN은 가능하다고 하는데 놀고 있는 Orange Pi 에 올려서 서비스를 해 보고자 방법을 찾아 공유를 합니다. 
Orange Pi 여서 Armbian 기준이며, id/password 방식을 사용하려면 mschapv2 플러그인이 필요한데 armbian 기본 패키지에서는 제공이 안되서 소스 컴파일 하여 설치를 하였습니다. 
Raspbian 에서도 잘 될 것으로 보이며, Raspbian 에서는 apt 설치 패키지에 mschapv2 플러그인이 있다면 설치 패키지를 사용하는 편이 시간이 절약될 것으로 보입니다.

 

1. Letsencrypt 인증서 발급

Ikev2 서버를 사용자 id/password 를 이용하여 접속하기 위해서는 인증서가 필요합니다.
무료인증서인 Let's Encrypt 인증서를 발급 받습니다.

# apt install certbot
# certbot certonly --rsa-key-size 4096 --standalone --agree-tos --no-eff-email --email your@email.com -d your_domain_name

 

2. 인증서 확인

인증서 발급이 성공하면 아래와 같이 인증서 파일이 있는 지 확인하고
인증서의 유효기간을 확인해 봅니다.

# ls -l /etc/letsencrypt/live/your_domain_name
lrwxrwxrwx 1 root root  42 Jul 29 22:36 cert.pem -> ../../archive/your.domain.name/cert1.pem
lrwxrwxrwx 1 root root  43 Jul 29 22:36 chain.pem -> ../../archive/your.domain.name/chain1.pem
lrwxrwxrwx 1 root root  47 Jul 29 22:36 fullchain.pem -> ../../archive/your.domain.name/fullchain1.pem
lrwxrwxrwx 1 root root  45 Jul 29 22:36 privkey.pem -> ../../archive/your.domain.name/privkey1.pem
-rw-r--r-- 1 root root 543 Mar  5 22:24 README
# certbot certificates
-------------------------------------------------------------------------------
Found the following certs:
  Certificate Name: your.domain.name
    Domains: your.domain.name
    Expiry Date: 2019-10-27 12:36:13+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/your.domain.name/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/your.domain.name/privkey.pem
-------------------------------------------------------------------------------

 

3. Strongswan Server download

아래 명령으로 Strongswan 최신버전을 다운로드합니다.
apt-get 으로 설치할 수 있는 Armbian 패키지는 mschapv2를 지원하지 않으므로 직접 소스에서 설치를 합니다.

# wget https://download.strongswan.org/strongswan-5.8.0.tar.gz

 

4. Strongswan Server Install

아래 명령으로 Strongswan Server를 소스에서 컴파일 하여 설치합니다..
설치되는 위치는 /usr/local/strongswan 입니다.

# tar xvzf ../down/strongswan-5.8.0.tar.gz
# cd strongswan-5.8.0
# ./configure --prefix=/usr/local/strongswan --sysconfdir=/etc --enable-openssl --enable-eap-mschapv2 --enable-md4 
# make 
# make install

 

5. 인증서 파일 링크

아래의 명령과 같이 1에서 발급 받은 인증서를 해당위치로 링크해 줍니다.
3군데 위치로 심볼릭 링크(또는 복사)해 주어야 하며, 아래에서 your.domain.name 부분을 자신의 도메인으로 수정해야 합니다.

# cd /etc/ipsec.d/certs
# ln -s /etc/letsencrypt/live/your.domain.name/chain.pem .
# ln -s /etc/letsencrypt/live/your.domain.name/fullchain.pem .

# cd /etc/ipsec.d/cacerts
# ln -s /etc/letsencrypt/live/your.domain.name/chain.pem .
# ln -s /etc/letsencrypt/live/your.domain.name/fullchain.pem .

# cd /etc/ipsec.d/private
# ln -s /etc/letsencrypt/live/your.domain.name/privkey.pem .

 

6. Strongswan Config

6.1 /etc/ipsec.conf 파일 수정

아래의 leftid 부분을 자신의 도메인으로 수정합니다.

# ipsec configuration <<
config setup
    charondebug="ike 1, knl 1, cfg 0"
    uniqueids=no

#define new ipsec connection
conn mytunnel-vpn
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    ike=aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes256-aes128-sha256-sha1-modp2048-modp4096-modp1024,aes256-sha1-modp1024,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-sha256-sha1-modp2048-modp4096-modp1024,3des-sha1-modp1024!
    esp=aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024,aes128-sha1,aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp2048-modp4096-modp1024,aes128gcm16,aes128gcm16-ecp256,aes256-sha1,aes256-sha256,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16,aes256gcm16-ecp384,3des-sha1!
    fragmentation=yes
    forceencaps=yes
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=@your.domain.name  <<-- 자신의 도메인으로 설정
    leftcert=fullchain.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightsourceip=10.10.1.0/24
    rightdns=1.1.1.1,8.8.8.8
    rightsendcert=never
    eap_identity=%identity

 

6.2 /etc/ipsec.secrets 파일 수정

파일을 아래와 같이 수정합니다.
2번째 줄 부터 id/pass 설정이며, 콜론(:) 좌측이 id, 콜론 우측의 "" 부분이 패스워드입니다.

: RSA "privkey.pem"
alice : EAP "myPassword"
tom : EAP "tomPassword"

 

6.3 /etc/iptables.sav 파일 수정 (iptables 포워딩 설정)

포트 포워딩을 위해 iptables 저장 파일을 수정해 줍니다. 

# Generated by iptables-save v1.6.1 on Mon Mar  4 21:22:51 2019
*nat
:PREROUTING ACCEPT [10:797]
:INPUT ACCEPT [1:104]
:OUTPUT ACCEPT [2:304]
:POSTROUTING ACCEPT [2:304]
-A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [116:14048]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
# for strongswan
-A INPUT -i eth0 -p udp -m udp --dport 500 -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --dport 4500 -j ACCEPT
-A INPUT -i eth0 -j DROP
COMMIT
*mangle
:PREROUTING ACCEPT [207:17257]
:INPUT ACCEPT [207:17257]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [116:14048]
:POSTROUTING ACCEPT [116:14048]
#-A PREROUTING -m conntrack --ctstate INVALID -j DROP
COMMIT

위에서 -A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE 부분의 10.10.1.0/24 를 /etc/ipsec.conf 에서 설정한 주소와 동일하게 맞춰 줘야 합니다.
중간 부분의 # for strongswan 부분이 strongswan 에서 사용하는 포트입니다. 
공유기를 사용할 경우 500번과 4500번 포트를 별도로 포트포워딩해 주어야 합니다.

파일 저장이 끝나면 아래 명령으로 iptables 에 변경 내용을 적용합니다.

iptables-restore < /etc/iptables.sav

 

6.4 ip 포워딩 기능을 활성화 해 줍니다.

/etc/sysctl.conf 파일에 net.ipv4.ip_forward=1 을 추가해 줍니다.
저장 후 아래의 명령어를 입력해서 적용합니다.
# sysctl -p

 

7. Strongswan Server 시작/중지/상태확인

# cd /usr/local/strongswan
# sbin/ipsec start
Starting strongSwan 5.8.0 IPsec [starter]...
# sbin/ipsec status
Security Associations (0 up, 0 connecting):
  none
# sbin/ipsec stop
Stopping strongSwan IPsec...

 

8. Strongswan Server 스크립트파일 생성

vi /lib/systemd/system/strongswan.service 로 스크립트 파일 생성 후 아래 내용으로 저장한다.

[Unit]
Description=strongSwan IPsec daemon using ipsec.conf
After=network-online.target

[Service]
ExecStart=/usr/local/strongswan/sbin/ipsec start --nofork
ExecReload=/usr/local/strongswan/sbin/ipsec reload
StandardOutput=syslog
Restart=on-abnormal

[Install]
WantedBy=multi-user.target

다음 명령으로 systemd 스크립트 적용

# systemctl daemon-reload
# systemctl enable strongswan

 

9. Strongswan Server 기동 및 상태확인

아래 명령으로 서버를 기동 후 상태를 확인합니다.

# systemctl start strongswan
# systemctl status strongswan

상태 확인 시 아래와 같이 Active: active 라고 표시 되어야 합니다.

# systemctl status strongswan
 strongswan.service - strongSwan IPsec daemon using ipsec.conf
   Loaded: loaded (/lib/systemd/system/strongswan.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-08-01 16:26:33 KST; 6min ago

 

10. 재부팅

서버를 재부팅 한 후 systemctl status strongswan 명령으로 상태를 확인해서 정상적으로 실행되면 완료입니다.

 

11. 안드로이드 클라이언트 설정

이제 서버측 설정은 완료되었으므로 안드로이드 기기의 구글 플레이에서 Strongswan 을 검색해서 설치해 줍니다.

설치 후 최초 실행화면입니다.

최초 실행화면

위 화면에서 우측 상단의 [ADD VPN PROFILE] 을 터치합니다.
그럼 아래와 같이 Profile 편집 화면이 나타납니다.

프로파일 편집 화면

아래 화면 처럼 각각의 항목을 넣어줍니다.

항목에 입력

Server: your.domain.name
VPN Type: IKEv2 EAP (Username/Password)
Username: alice
Password: 서버설정시 패스워드
CA certificate: Select automatically 체크함
Profile name: MyVPN(임의로 입력)

우측 상단의 SAVE를 터치해서 저장을 하면 아래 처럼 입력한 Profile 이 생성됩니다.

생성된 프로파일

위 화면에서 생성된 프로파일을 터치하면 서버에 접속을 시도하고 성공하면 아래와 같이 Connected 라고 표시됩니다.

상단알림바를 보시면 VPN 이라는 알림이 생깁니다. 이 상태에서 구글에서 My IP로 검색해서 내 IP를 확인해 보면 IP가 VPN IP로 바뀐 것을 확인할 수 있습니다.

접속된 화면

 

Notepad++ 64bit Hex Editor 플러그인 설치

유틸리티/Notepad++

Notepad++ 64bit 버전에서는 디폴트로 설치 가능한 플러그인이 많지 않으므로 플러그인을 사용하려면 32비트 버전을 설치하는 편이 좋다.

하지만 64비트를 사용할 필요가 있을 때 Hex Editor 플러그인을 사용하려면 다음 과 같은 방법으로 설치한다.

Notepad++ 7.6.x 에서 Test됨


먼저  https://github.com/chcg/NPP_HexEdit/releases 에서 HexEditor_0.9.8_x64.zip 파일을 다운로드 받는다.

64비트 버전이라면

C:\ProgramData\NotePad++\plugins\ 아래

HexEditor 폴더를 생성하고 그 안에 위에서 다운받은 zip 파일 안에 압축되어 있는 HexEditor.dll 파일을 복사해 넣는다.


이 후 Notepad++ 을 재시작 한 후에 플러그인 메뉴에 Hex-Editor 가 표시되면 정상적으로 설치된 것이다.

Hex-Editor - Option 에서 원하는 색상과 폰트를 설정해 주면 된다.



CMake 플랫폼 체크하기

프로그래밍

1개의 소스로 서로 다른 운영 체제에서 컴파일 및 실행되는 소프트웨어를 생성하길 원한다면, 각각의 플랫폼(OS)간의 특별한 속성을 파악해야 한다.

서로 다른 플랫폼(운영 체제) 간에는 미묘한 차이가 있다.

예를 들어 FreeBSD에서는 malloc.h를 사용하지 않아야 하고, 반면에 Linux에서 사용할 수 있다.

이러한 차이는 통상 config.h 라고 불리는 각 플랫폼의 특성을 구분짓는 여러개의 define문을 포함하는 헤더파일을 통해 처리된다.

#define HAVE_MALLOC_H 1 /* #undef HAVE_SYS_MNTTAB_H 1 */ /* #undef HAVE_SYS_MNTENT_H 1 */ #define HAVE_SYS_MOUNT_H 1

이 헤더파일은 아래 예제 처럼 소스의 맨 처음에 include 되어 처리 된다.

foo.c: #include "config.h" #ifdef HAVE_MALLOC_H #include <malloc.h> #else #include <stdlib.h> #endif void do_something() { void *buf=malloc(1024); ... }

config.h의 내용은 소스가 컴파일 되는 플랫폼에 따라 달라야 하므로, 실제로 컴파일 되기 전에 헤더 파일이 생성되어야 한다.

Autotools 기반 소프트웨를 사용중이라면, make 전 단계에서 실행되는 ./configure 단계를 알고 있을 것이다.

./configure 스크립트는 시스템 내부 검사를 수행하고 수집 된 정보로부터 config.h 헤더 파일을 생성한다. 

여기서는 CMake서도 ./configure를 사용하는 것과 똑같이 할 수 있는 방법에 대해 설명할 것이다.

또한 내장 명령에 있어서도, CMake는 module이라고 불리는 스크립트 파일을 사용해서 더 많은 명령을 지원한다.

이 파일들은 cmake 모듈 디렉토리에 있으며, UNIX 시스템의 경우 디폴트로 /usr/local/share/CMake/Modules 디렉토리 이다.

이러한 모듈의 명령을 사용하려면 먼저 CMakeLists.txt 파일 안에 include 를 해 줘야 한다.

CMake에는 시스템을 체크하기 위한 몇 가지 모듈이 포함되어 있다.

예를 들면 CHECK_INCLUDE_FILES :

INCLUDE (CheckIncludeFiles) # usage: CHECK_INCLUDE_FILES (<header> <RESULT_VARIABLE> ) CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H) CHECK_INCLUDE_FILES ("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)

CMake 모듈 CheckIncludeFiles는 CHECK_INCLUDE_FILES() 명령을 사용할 수 있게 해 준다.

이 명령의 첫 번째 인수는 체크하려고 하는 헤더파일이다. 두 번째 인수는 결과를 돌려받을 변수이다.

주어진 헤더가 발견되면 두번째 인수의 변수가 1로 설정되고, 그렇지 않으면 빈 상태로 된다.

헤더를 사용하기 위해 다른 헤더가 필요한 경우 위의 예에서 보듯이 헤더들을 세미콜론으로 구분해서 나열해야 한다.

더 정확한 CHECK_INCLUDE_FILES()의 구현에 대해서는 /usr/local/share/CMake/Modules/CheckIncludeFiles.cmake 을 참고하면 된다.

지정된 헤더 파일에 대한 테스트 결과는 CMakeCache.txt 파일에 아래 예와 같이 저장되므로, 나중에 테스트가 성공했는지 여부를 확인하려는 경우

CMakeCache.txt 파일을 살펴보면 된다.

//Have include HAVE_MALLOC_H HAVE_MALLOC_H:INTERNAL=1

결과가 캐시에 있으면 테스트가 다시 실행되지 않으므로, 다시 실행하려면 CMakeCache.txt 파일을 삭제하거나 다시 테스트 하려는 변수 항목을 삭제해야만 테스트가 다시 실행될 수 있다.

테스트가 실패한 경우 이유를 찾고 싶다면 CMakeFiles/CMakeError.log 파일을 열어서 헤더 이름 (또는 함수 등)을 찾으면 거기에 실패한 코드가 표시되어 있다.

이제 우리는 예를 들어 malloc.h가 존재하는 지 테스트 하고 cmake 변수 HAVE_MALLOC_H에 결과를 얻었으므로, 이제 헤더 config.h를 만들어야 한다.

이를 위해 cmake 명령 CONFIGURE_FILE()을 사용해야 한다.

이것은 소스 파일을 대상 파일로 복사하면서 원하는 부분을 수정해 주는 역할을 한다.

먼저 config.h.in이라는 이름의 소스 파일을 작성해야 한다. (이름은 아무래도 좋지만 autotools에서는 통상 config.h.in으로 사용한다) :

#cmakedefine HAVE_MALLOC_H 1 #cmakedefine HAVE_SYS_MOUNT_H

cmake가 실행되면 위 구문 중 #cmakedefine이 대체된다. HAVE_MALLOC_H 및 HAVE_SYS_MOUNT_H가 true이면 아래와 같은 config.h가 생성된다.

#define HAVE_MALLOC_H 1 #define HAVE_SYS_MOUNT_H

만약 2개 변수 모두 false 이면 아래와 같은 파일이 생성된다.

/* #undef HAVE_MALLOC_H */ /* #undef HAVE_SYS_MOUNT_H */

이 헤더를 소스 파일에 포함 시키고 #ifdef를 사용해서 속성을 확인할 수 있다.

이러한 체크를 최상위 CMakeLists.txt 만이 아니라 프로젝트의 모든 CMakeLists.txt에 추가할 수 있다.

구성된 헤더가 여러 개인 경우에는 그것들을 모두 config.h라고 부르면 include에 문제가 생길 수 있다.

각 서브 디렉트리에 따라 config.h, foo/ 디렉토리는 config-foo.h, bar/ 디렉토리는 config-bar.h 와 같은 이름을 지정하는 편이 좋다

시스템 검사를 수행하는 cmake의 다른 명령들은 다음과 같다.

Module: INCLUDE (CheckIncludeFiles) Usage: CHECK_INCLUDE_FILES(headers variable) Example: CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H)

지정된 헤더파일이 존재하는 지 여부를 판정.

Module: INCLUDE (CheckFunctionExists) Usage: CHECK_FUNCTION_EXISTS(function variable) Example: CHECK_FUNCTION_EXISTS(madvise HAVE_MADVISE)

지정된 함수가 존재하는 지 여부를 판정.

Module: INCLUDE (CheckSymbolExists) Usage: CHECK_SYMBOL_EXISTS(symbol headers variable) Example: CHECK_SYMBOL_EXISTS((LC_MESSAGES "locale.h" HAVE_LC_MESSAGES)

지정된 헤더가 존재하는 경우에, 지정된 기호가 존재하는 지 여부를 판정 "Symbol"은 Preprocessor 매크로 또는 주소를 사용할 수 있으며, Enumerate 형은 사용 될 수 없음

Module: INCLUDE (CheckLibraryExists) Usage: CHECK_LIBRARY_EXISTS(library function location variable) Example: CHECK_LIBRARY_EXISTS(volmgt volmgt_running "" HAVE_VOLMGT)

지정된 라이브러리가 존재하고 제공된 함수를 포함하는지 여부를 확인. 이것은 함수를 사용하는 작은 프로그램과 라이브러리에 대한 링크를 통해서 수행. 필요한 경우 추가 링크 디렉토리 위치 매개 변수(-Ldir)를 지정할 수 있다.

Module: INCLUDE (CheckTypeSize) Usage: SET(CMAKE_EXTRA_INCLUDE_FILES header) CHECK_TYPE_SIZE(type variable) SET(CMAKE_EXTRA_INCLUDE_FILES) Example: SET(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) CHECK_TYPE_SIZE("struct ucred" STRUCT_UCRED) SET(CMAKE_EXTRA_INCLUDE_FILES)

지정된 타입이 존재하는 지 여부를 판정 해, 그 타입의 크기를 돌려줌. 변수 안에는 타입의 크기가 설정되며, 타입이 존재한다면 HAVE_STRUCT_UCRED는 true로 설정됨. 타입의 크기에는 관심이 없고, 단순히 타입이 존재하는 지 여부만 알고 싶다면 STRUCT_UCRED 를 직접 사용할 수 있다. 타입이 없을 경우 이 값은 FALSE로 평가된다.(HAVE_STRUCT_UCRED).

Module: INCLUDE (CheckPrototypeExists) Usage: CHECK_PROTOTYPE_EXISTS(function headers variable) Example: CHECK_PROTOTYPE_EXISTS(mkstemps "stdlib.h;unistd.h" HAVE_MKSTEMPS_PROTO)

헤더가 주어진 것에 대한 선언을 제공하는지 여부를 확인. 함수가 실제로 정의되었는 지 여부는 확인하지 않음.

Module: INCLUDE (CheckCXXSourceCompiles) INCLUDE (CheckCSourceCompiles) Usage: CHECK_CXX_SOURCE_COMPILES(source variable) CHECK_C_SOURCE_COMPILES(source variable)

소스 코드가 컴파일되고 링크되는지 여부를 확인. CMAKE_REQUIRED_LIBRARIES, CMAKE_REQUIRED_FLAGS 및 CMAKE_REQUIRE 를 설정할 수 있음