OpenVPN 은 기본적으로 사용자별로 인증서를 생성해서 연결하도록 하고 있다.


그러다보니 설정파일에 ca, tls-auth, cert, key 4개의 파일이 추가로 따라다니게 되는데 관리하기 조금 번거로운 면이 있다.

물론 각각 ovpn 파일안에 임베딩해버릴 수 있지만...


아이디, 비밀번호로 로그인하는 방법이 있길래 진행해보았다.


먼저 OpenVPN 서버 설정에서 아래 두 문구를 추가한다.

client-cert-not-required
auth-user-pass-verify "/etc/openvpn/userauth/verify.sh" via-file

첫번째 줄은 클라이언트 인증서가 필요없게 하는거고, 두번째줄은 비밀번호를 체크할 스크립트를 지정한다.

저 파일은 내가 만들어줘야하며, 경로는 어디두던 크게 상관없음.


다만 user nobody / group nogroup 설정을 했을 경우 OpenVPN 데몬이 nobody / nogroup 권한으로 작동하기 때문에, 권한에 유의해주면 된다. 읽기 권한이나 실행 권한 등이 없으면 비밀번호 체크를 할 수 없다.

비밀번호 체크 과정에 root 권한이 필요하다면 권한을 낮추는 해당 설정을 제거해주자.


스크립트 경로 뒤의 via-file 은 OpenVPN 에서 사용자가 입력한 아이디와 비밀번호를 넘겨줄 방식을 정한다.

via-file 로 할 경우 임시 파일을 생성하면서

username
password

이렇게 두 줄로 된 파일을 생성한다.


(via-env 로 할 경우 환경변수에 넣어준다는데, 사용자명은 들어오는데 비밀번호는 어디있는지 모르겠더라...)



해당 스크립트에서 아이디와 비밀번호를 읽어서, 성공했다면 exit 0 을, 실패했다면 에러코드와 함께 프로그램이 종료되면 된다.



이제 비밀번호 체크를 위한 스크립트를 만들자.

방식은 다양하니 직접 만들면 되겠지만 내 스크립트를 참고 삼아 올려둠.


아래 URL 에 들어가보면 다른 스크립트들도 있다.


나는 user.pass 파일에

사용자명=SHA1비밀번호
사용자명=SHA1비밀번호

꼴로 저장을 해두고, 이를 검사하는 방식으로 작성하였다.


verify.sh 코드는 이렇게.

#!/bin/bash
passfile="/etc/openvpn/userauth/user.pass"
logfile="/var/log/openvpn/userauth.log"

username=`head -n 1 $1`
password=`head -n 2 $1 | tail -1`

hashed=`echo -n $password | sha1sum | awk '{print $1}'`
userpass=`cat $passfile | grep $username= | awk -F= '{print $2}'`

if [ "$userpass" = "$hashed" ]; then
        echo "`date +'%Y-%m-%d %H:%M:%S'` - auth success: $username" >> $logfile
#       echo "ok"
        exit 0
fi

echo "`date +'%Y-%m-%d %H:%M:%S'` - auth fail: $username" >> $logfile
#echo "not ok"
exit 1



그리고 client 설정 파일에는 cert 와 key 를 없애고, auth-user-pass 옵션을 추가해주면 된다.



----------

이 다음으로, Local 사용자 계정으로 로그인하는걸 시도해보았다.


보통 shadow 파일을 읽어서 비교를 많이 하던데, 나는 PAM Authentication 을 이용해보았다.

PAM 인증을 할때 root 이어야만 제대로 작동하는 것 같으니, 서버 설정에서 user nobody 옵션은 주석처리 해주자. (혹은 스티키 비트를 넣어주거나..)



PAM 인증을 하는 c 프로그램을 제작하였고, 로그를 남기기 위해 간단한 쉘 스크립트를 같이 이용하였음.

verify.sh

#!/bin/bash
pam_auth="/etc/openvpn/userauth/pam_auth"
logfile="/var/log/openvpn/userauth.log"

pam_result=`$pam_auth $1`
ret=$?

echo "`date +'%Y-%m-%d %H:%M:%S'` $pam_result" >> $logfile
exit $ret



pam_auth.c ( https://gist.github.com/iolate/a58b73a023b35d5f181814de2f4ffccd )

// gcc -o pam_auth pam_auth.c -lpam

#include <security/pam_appl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int custom_converation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr) {
	// Provide password for the PAM conversation response that was passed into appdata_ptr
	struct pam_response* reply = (struct pam_response* )malloc(sizeof(struct pam_response));
	reply[0].resp = (char*)appdata_ptr;
	reply[0].resp_retcode = 0;

	*resp = reply;
	return PAM_SUCCESS;
}

int main(int argc, char *argv[]) {
	if (argc != 2) {
		fprintf(stderr, "Usage: %s [filepath]\n", argv[0]);
		exit(1);
	}
	
	FILE* fp;
	char* username = NULL;
	char* password = NULL;
	size_t len = 0;
	ssize_t read;
	
	fp = fopen(argv[1], "r");
	if (fp == NULL) {
		fprintf(stderr, "%s: Cannot open '%s'\n", argv[0], argv[1]);
		return 1;
	}
	
	read = getline(&username, &len, fp);
	if (read == -1) {
		fclose(fp);
		return 1;
	}
	username[strlen(username)-1] = '\0'; // remove LF
	
	read = getline(&password, &len, fp);
	if (read == -1) {
		fclose(fp);
		return 1;
	}
	password[strlen(password)-1] = '\0'; // remove LF
	
	fclose(fp);
	
	// PAM Authentication
	struct pam_conv conv = {custom_converation, password};
	pam_handle_t* pamh = NULL;

	int retval = pam_start("whoami", username, &conv, &pamh);

	if (retval == PAM_SUCCESS)
		retval = pam_authenticate(pamh, 0); // is user really user?

	//if (retval == PAM_SUCCESS)
	//	retval = pam_acct_mgmt(pamh, 0); // permitted access?

	if (retval == PAM_SUCCESS) {
		fprintf(stdout, "Authenticated - %s\n", username);
	} else {
		fprintf(stdout, "Not Authenticated - %s\n", username);
	}

	pam_end(pamh, 0);
	return retval;
}


pam_auth 를 컴파일하기 위해선 pam development 패키지가 필요하니 설치하고 컴파일 해주자.

Ubuntu 기준 아래의 방법으로 진행하면 됨.

sudo apt install libpam0g-dev
gcc -o pam_auth pam_auth.c -lpam



verify.sh 를 간단히 수정하면, 두가지 방식을 동시에 사용하는 것도 가능하다.


참고

https://forums.openvpn.net/viewtopic.php?t=24907

https://medium.com/@nqbao/openvpn-auth-user-pass-verify-example-8d99023f08f7


https://unix.stackexchange.com/a/153323

http://www.linux-pam.org/Linux-PAM-html/adg-example.html

Ubuntu 18.04 에 NIS 를 구성하여 사용하고 있었음.


설치 및 설정은 아래 링크를 참고.


Ubuntu 18.04 : NIS Server

(01) Configure NIS Server

(02) Configure NIS Client

(03) Configure NIS Slave


나는 Slave 서버는 없고, MERGE_PASSWD 와 MERGE_GROUP 옵션은 뭔지 잘 모르겠어서 하라는대로 하지 않았음.


위 방법으로 1대의 Master 와 여러대의 Client 를 구성하였는데, Client에서 NIS 계정으로 로그인할 경우 SSH 연결을 위해서 20초 가량이 걸리면서 연결이 제대로 안되는 문제가 발생.


ssh -vvv 옵션을 주고 연결을 하면


(생략)

debug1: Entering interactive session.

debug1: pledge: network

(여기서 약 20초 딜레이)

debug3: receive packet: type 80

debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0

(생략)


이렇게 진행이 된다.


/var/log/auth.log 를 보면

sshd[15635]: pam_systemd(sshd:session): Failed to create session: Connection timed out


이런 식의 오류메시지가 남겨져 있음.


찾아보니 systemd-logind 에 IP Sandbox 기능이 있는데 이와 관련한 문제이며 이 기능을 꺼줘야 한다고 한다.

보안상의 문제로 이걸 끄면 대체로 IP 필터를 걸어줘라~ 라는 식으로 적혀 있던데 이 기능 자체가 새로 생긴 것 같아 보이고 필요성을 모르겠어서 그냥 비활성화만 하고 치움.



sudo vi /lib/systemd/system/systemd-logind.service
SystemCallArchitectures=native
LockPersonality=yes
#IPAddressDeny=any
FileDescriptorStoreMax=512


sudo systemctl daemon-reload
sudo systemctl restart systemd-logind


참고

https://github.com/systemd/systemd/issues/9431

https://askubuntu.com/questions/1031022/using-nis-client-in-ubuntu-18-04-crashes-both-gnome-and-unity/1064617#1064617

Vinpok Split을 정발한다는 얘기를 중고거래 판매자에게 들었는데, 그게 주연테크 캐리 뷰 라는 이름인 것 같다.


https://www.funshop.co.kr/goods/detail/66537

289,000원에 판매중.


직접 보진 않았지만, 제품 페이지만 보았을때는 가운데 로고 정도가 추가된 것 같다.

그 외 이상한 차이점들은 후술.


그리고 사용기를 좀 더 반영해서 글 수정하였음.


----------


원래 ASUS MB16AC 를 사용하고 있었는데, 어쩌다보니 ASUS 제품은 친구 주고 Vinpok Split 을 구매하게 되었다.

ASUS 는 오픈마켓에서 바로 구입했었고, Vinpok Split 은 인디고고 제품인데, 중고로 구매함.


비슷한 두 제품을 써보게 된 김에 쓰는 간단한 비교글.


명칭은 각각 그냥 ASUS, Vinpok 으로 작성하겠음.


일단 둘다 USB-C Displayport Alt Mode 를 지원하는 휴대용 모니터가 기본 카테고리이다.

그리고 15.6인치, IPS패널이며 1920x1080을 최대 해상도로 지원하는 공통점이 있는 제품.

스펙상 차이점은 아래 표 참고.

화면 크기와 정성적 지표인 표면처리를 제하면 Vinpok 제품이 미묘하게 우위를 점하고 있다.


 

ASUS MB16AC 

 Vinpok Split

 주연테크 캐리 뷰

 크기

 359.7 x 226.4 x 8.0 mm

 353.7 x 223.5 x 4.4~8.8 mm

 353.7 x 223.5 x 4.8~9.5 mm

 화면 크기

 344.16 x 193.59 mm

 343.92 x 193.80 mm

 344.16 x 193.59 mm

 최대 밝기

 220 cd/㎡

 280 cd/㎡

 250 cd/㎡

 명암비

 800:1

 1000:1

 800:1

 무게

 780g

 625.9g

 660g

 표면

 Glare

 ? Hard Coating-3G


주연테크 캐리 뷰가 정발된걸 보면서, 펀샵의 제품 스펙을 추가하였는데, 스펙이 좀 이상하다.

정발되면서 좀 더 개선이 이루어졌을 수도 있겠지만, 큰 틀에서


우선 크기에서 두께는 Vinpok 쪽이 내가 실측한 것이기 때문에 펀샵쪽이 맞을 것 같은데,

화면크기가 펀샵의 정보가 ASUS와 동일한 것을 보면 펀샵 측이 복붙하면서 오류를 낸게 아닐까 생각된다.


무게, 최대 밝기, 명암비 역시 Vinpok Split의 스펙표와 펀샵의 스펙표가 다른데, 인디고고 상품이였으니 이 부분에 대해선 펀샵 측 정보가 맞지 않을까 생각함.




각 제품 상자이다. Vinpok 은 적힌 내용이 아무것도 없는데, 중고로 구매한 것이다보니 원래 이게 다인지는 확실하지 않음.




먼저 ASUS, Glare 처리된 디스플레이가 거울처럼 주변을 비추는게 보이고

거치대겸 커버와 USB-C 케이블, 전용 볼펜과 USB-A to C 젠더가 포함된다.



이쪽은 Vinpok.

표면처리가 정확히 어떤건진 모르겠으나 Glare 코팅이 되어있진 않다.

거치대 겸 커버와 USB-C 케이블, USB-A - USB-C 케이블, mini HDMI - HDMI 케이블이 포함된다.


원래 맥북 모니터에 클립으로 결합시켜서 사용하는게 컨셉으로 나온 제품이었는데 그 클립이 별매로 판매된다고 한다.

클립을 $9로 구매하였는데 언제올지는 모르겠음.




ASUS 위에 Vinpok을 올려보았다. 정말 미세하게 ASUS가 크다.




이쪽은 후면.


전면과 반대로 후면은 Vinpok 이 거울처럼 주변을 비추는 모습..ㅎ

Vinpok은 특이하게 상표를 포함하여 아무런 글씨도 적혀있지 않다.



   


전면 기준 좌측 측면 / 우측 측면


Vinpok 이 얇은 부분(4.4mm)은 ASUS(8mm)에 비해 얇은데, 아래쪽 두꺼운 부분은(8.8mm) ASUS에 비해 조금 더 두꺼움.


ASUS 는 좌측에 USB-C 하나가 끝


Vinpok은 좌측에 전원공급용 USB-C 포트, 설정 버튼과 다이얼이 있고,

우측에 mini HDMI 와 display input 용 USB-C, AUX 가 있다.


조작버튼이 쉽게 부러질 정도로 약하다는 리뷰를 보았는데, 잠깐 만져본 느낌으로 그 정도는 아닌 것 같음.



커버를 덮은 모습.

Vinpok 은 전용 커버가 후면 두꺼운 부분은 덮지 않게끔 만들어져있다.

ASUS 는 커버가 전후면을 다 덮음.



기본 커버를 이용해 세운 모습.

ASUS 는 다양한 방식으로 세울 수 있으면서 안정적이었던 반면에, Vinpok은 안정적이지 못하다.

지지하고 있는 저 커버가 잘 고정되지 않으면 계속 뒤로 점점 벌어지는 형태.

수시로 보정을 해주거나 앞뒤로 다른 물건을 두어 고정해줘야 한다.




둘이 같이 Macbook Pro 에 연결해보았다.

프로파일이나 밝기 등을 제대로 설정하지 않았으니 색 표현을 참고하지는 말고... 그냥 정면샷 정도...




(코팅에 따른 차이.. ASUS 는 거울처럼 앞이 비친다.)


아무래도 Glare 코팅에 따른 느낌 차이가 큰 것 같다.

개인적으로는 Glare 코팅을 선호.




Vinpok 은 터치도 지원한다!

지원되는 안드로이드폰에 연결하였을 경우 10포인트 멀티터치를 지원하고,

Mac 의 경우 별도 설정없이 1포인트 마우스처럼 사용할 수 있다.


조금 요상하게 작동하고 비활성화를 포함해서 아무런 설정이 없어서 애매하긴 한데 간단하게 사용하기는 좋을 것 같음.

비활성화 옵션과 터치/마우스 모드 전환만 있어도 정말 좋았을 것 같다.


----------


Vinpok 사용기 추가


1. iOS와의 연결

펀샵의 주연테크 제품에 된다고 나와있어서 작성.

iPhone X, iPad Pro 9.7 과 애플정품 USB-C to Lightning 으로 연결해보았으나 화면이 나오지 않는다. HDMI로 연결해야할 것 같음.

충전은 또 됨(?)


2. Nintendo Switch와 연결

매우 잘되는데, 충전기를 연결해야만 작동한다.


3. Samsung Galaxy 폰과 연결 (정확한 모델은 모르겠음)

일단 화면이 미러링으로도 나오고, Dex 모드로 들어갈 수 있다는 알림이 폰에 나온다.

Dex 로 들어가면 데스크톱 컴퓨터와 비슷한 UI로 바뀌는데, 이상한 점은 두 모드 다 터치가 안된다...

Dex 모드에서는 휴대폰을 트랙패드처럼 사용하게 되는 구조...


뭔가 문제가 있는 것 같지만 일단 내가 갤럭시를 안쓰기 때문에 그러려니 넘어감.


4. 설정 저장 문제

다른 설정은 안건드려봐서 모르겠고, 밝기 설정 저장이 안된다....

항상 전원을 넣으면 30% 정도로 고정됨. 이유는 모르겠음....



----------


정리하자면,


* ASUS의 장점

국내 정식 판매. A/S에 유리할 듯 함 (캐리 뷰는 정발했으니 상쇄되려나?)

기본 커버로 거치가 좀 더 편리하고 좋음


* Vinpok의 장점

HDMI 지원

닌텐도 스위치 지원 (정품독이 아니면 원래는 USB-C 직접 연결 디스플레이는 지원하지 않는다)

스피커 존재 (난 안써봤는데 평이 정말 구리다고... 맥북 스피커가 좋기 때문에 써볼 생각조차 하지 않았다.)

터치 가능

저렴 (펀딩 상태에 따라 가격 변화 가능... 일단은 저렴)


* 장/단점과 별개로 Glare 코팅 차이


정도가 될 것 같다.



Vinpok 이 내구성이나 고장이 조금 걱정되긴 하지만... 일단은 잘 써볼 예정!


+ Recent posts