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 이 내구성이나 고장이 조금 걱정되긴 하지만... 일단은 잘 써볼 예정!




웹 ssh 클라를 찾다가 발견한 프로그램.


사용자인증 및 사용자에 따른 커넥션 설정에다가 SSH 는 기본이고 RDP와 VNC 까지 지원을 한다.

RDP 테스트를 해봤는데 매우 쓸만한 수준.

심지어 모바일까지 잘 지원을 한다!


tomcat 위에서 돌아간다는 점만 제외하면 정말 마음에 드는데.... tomcat 은 싫으니 docker 에다가 넣어버리자.


guacamole 는 커넥션을 유지하면서 서버 역할을 해주는 데몬과 프론트엔드 인스턴스 2개로 분리되어 있다.

docker에서 각각 guacamole/guacd (데몬), guacamole/guacamole (프론트) 이미지를 사용하면 됨.


사용자와 연결설정 저장 등을 위해 mysql 등의 DB를 사용하게 되고 보통 이것까지 docker 로 돌리지만, 난 내 DB에 연결할 것이므로 생략.


먼저 이미지를 받아온다.

docker pull guacamole/guacd
docker pull guacamole/guacamole


그리고 도커 이미지에서 mysql 테이블 생성을 위한 스크립트를 가져온다.

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql


사용자나 DB는 알아서 생성을 하고, 해당 스크립트로 DB 구성을 한다.

mysql -hhost -uuser -p db_name < initdb.sql


컨테이너 설정을 위해서 docker-compose 를 사용한다.

없다면 설치를 해주고.. 아래 내용으로 docker-compose.yml 파일을 만든다.

version: '3'
services:
  guacd:
    hostname: guacd
    image: guacamole/guacd
    restart: always

  guacamole:
    image: guacamole/guacamole
    restart: always
    ports:
      - 8080:8080
    links:
      - guacd
    environment:
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: DB_HOST
      MYSQL_DATABASE: DB_DATABASE
      MYSQL_USER: DB_USER
      MYSQL_PASSWORD: DB_PASSWORD


그리고 아래 명령어를 치면 아래처럼 컨테이너가 생성됨!

docker-compose up -d
Creating network "guacamole_default" with the default driver
Creating guacamole_guacd_1 ...
Creating guacamole_guacd_1 ... done
Creating guacamole_guacamole_1 ...
Creating guacamole_guacamole_1 ... done


이제 http://서버주소:8080/gucamole 로 들어가면 로그인창을 볼 수 있다.


기본 계정(위 mysql 설정을 통해 자동 생성됨)은 ID: guacadmin / PW: guacadmin



nginx 등으로 라우팅을 해주면 편하게 쓸 수 있을 듯.

apache2 나 nginx 에서 프록시 설정은 https://guacamole.apache.org/doc/gug/proxying-guacamole.html 을 참고하자.



참고 URL:

https://pages.wiserain.com/articles/deploying-guacamole-using-docker/

https://guacamole.apache.org/doc/gug/proxying-guacamole.html

Win Server 2012 + Hyper-V 조합으로 쓰다가 도저히 불편해서 결국 Host 를 Linux 계열로 밀어버리는 대 공사 진행.


Ubuntu 18.04 + KVM 조합으로 결정했다.

Host 에서는 no GUI 로, SSH를 통해 설치 및 사용하고, KVM 가상머신 생성 및 설정은 X11 forwarding 을 통해 진행함.



KVM 설치

sudo apt install qemu-kvm libvirt-bin bridge-utils ubuntu-vm-builder

# GUI manager
sudo apt install virt-manager



이후 VM 관련 작업을 할때 매번 sudo 를 이용하고 싶지 않다면, 관련 그룹에 계정을 추가해준다.


그냥 설치만 해도 내 사용자 계정이 libvirt 그룹에 자동으로 추가되던데, 다른 계정을 이용했거나 필요에 따라 진행.


보통 libvirt, kvm, libvirtd 3개 그룹에 집어넣던데 환경에 따라... 난 이미 libvirt 그룹엔 속해져있었고 libvirtd 그룹은 생성이 안되어 있어서, kvm 에만 추가해두었다,

sudo adduser $(id -un) libvirt
sudo adduser $(id -un) kvm

# 나의 경우 libvirtd 그룹은 없었음
# sudo adduser $(id -un) libvirtd


가상머신 설치

가상머신 설치용 이미지나, 디스크는 기본적으로 /var/lib/libvirt/images 경로를 참조하고 사용한다. 필요하면 바꿔주면 되겠지만, 난 귀찮아서 그대로 사용, 설치 전 iso 이미지를 저기다가 넣어주었다.


커맨드라인으로 생성하고 관리하는 방법도 있는데, 난 X11 forwarding 을 사용.

ssh 연결시에 -X 옵션을 넣어주고 연결한다.


* Mac 이라면 XQuartz 를 설치해줘야한다.

또한 XQuartz 실행시에 키보드가 한글로 되어 있다면 이후에 계속 키 입력이 이상하게 되니 주의해주자.

그리고 연결 끊고 재연결시엔 독에서 XQuartz 를 직접 끄고 다시 연결해줘야하는 듯...


ssh -X user@host

$ virt-manager



그럼 이런 창이 뜬다. 이 상황에서 가상머신 생성, 설정, 콘솔보기 등을 할 수 있음.


생성은 알아서 하는걸루.. 별거 없다.



네트워크 관련 설정

브릿지 NIC 생성 및 사용하기

기본적으론 virbr0 란 이름으로 NAT NIC 만 생성해준다.


1. br0 인터페이스 생성

Ubuntu 17? 18? 부터 네트워크 인터페이스 관리를 위해 netplan 패키지를 이용한다.

설정 파일 경로는 /etc/netplan/


적당히 60-kvm.yaml 이란 이름으로 만들어서 br0 네트워크 인터페이스를 생성해준다.

eno1 은 브릿지 하려는 NIC 이름. br0 도 필요하다면 이름을 바꿔줄 것.


sudo vi /etc/netplan/60-kvm.yaml
network:
  version: 2
  bridges:
    br0:
      dhcp4: false
      interfaces: [eno1]
# 설정 적용
sudo netplan apply


적당한 경로에 아래 내용을 가진 br0.xml 파일을 만들고 그 밑 명령어로 KVM NIC를 설정해준다.

<network>
        <name>br0</name>
        <forward mode='bridge'/>
        <bridge name='br0'/>
</network>
virsh net-define br0.xml
virsh net-start br0
virsh net-autostart br0


이 후 아래와 같이 확인할 수 있다.

virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 br0                  active     yes           yes
 default              active     yes           yes


이제 NIC 설정에 "Virtual network 'br0' : Bridge network 가 나타나서 사용할 수 있다.

virt-manager 로 새 VM을 만들땐 NIC 를 하나밖에 선택을 못할텐데,

마지막 단계에 "Customize configuration before install" 체크박스가 있고, 이걸 체크하면 뜨는 설정 창에서 Add Hardware 를 통해 NIC 를 추가할 수 있다.






NAT 고정 IP 설정하기

기본으로 생성되는 NAT NIC 는 IP 를 DHCP 로 할당한다.


가상머신에서 static ip 를 설정해줘도 되겠지만, host에서 특정 Mac 주소에 대해 고정 IP 를 할당하는 방법



virsh net-edit default
# 처음이라면 에디터를 선택하라고 뜰텐데 편한걸 선택하면 된다. 난 vim basic.

<ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
      <host mac='52:54:00:FF:FF:FF' name='NAME' ip='192.168.122.XXX'/>
    </dhcp>
  </ip>
</network>


dhcp 부분을 찾아서 위와 같이 특정 맥 어드레스에 대해 아이피 주소를 할당해준다.


이 후 아래 명령어를 통해 변경사항 적용.



virsh net-destroy default
virsh net-start default


블루투스를 이용해서 쉘에 접근할 수 있는 방법이 있다고 해서 정리해봄.


와이파이를 제대로 사용할 수 없는 등의 환경에 유용할 것 같은데.. 마냥 편하진 않다. 느리기도 하고...


0. bluetoothd 실행 옵션

bluez 5 부터 일부 커맨드라인 툴들이 deprecated 되었다.

hciconfig 는 바로 지원을 하는 것 같은데, SPP 추가를 위한 sdptool 이 작동하지 않음.


sudo vi /lib/systemd/system/bluetooth.service

ExecStart=/usr/lib/bluetooth/bluetoothd -C

데몬파일을 열어서 이렇게 수정해주자.(마지막에 -C 옵션 추가)



sudo systemctl daemon-reload
sudo systemctl restart bluetooth

그 후 블루투스 서비스를 재시작해주면 된다.



1. SP profile 추가

RPi 의 블루투스 프로파일에 SPP, Serial Port Profile 을 추가해야한다.


sudo sdptool add SP

위 명령어로 추가 가능. 재부팅, 서비스를 재시작 등을 하면 없어진다.

이 작업을 자동으로 해주고 싶으면,

블루투스 데몬 파일(/lib/systemd/system/bluetooth.service)에 아래와 같이 추가해줘도 됨.


ExecStartPost=/usr/bin/sdptool add SP

# 데몬 파일을 수정해줬으면 리붓하거나 reload & restart 해주자.
sudo systemctl daemon-reload
sudo systemctl restart bluetooth


추가가 되었는지는 아래와 같이 확인할 수 있다.


sudo sdptool browse local
(...)
Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10005
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100



2. 다른 장치에서 파이를 검색 가능하게 설정


# Page Scan & Inquiry Scan
sudo hciconfig hci0 piscan 
#OR
sudo btmgmt connectable on
sudo btmgmt discov yes

# Page Scan (기본값)
sudo hciconfig hci0 pscan
#OR
sudo btmgmt connectable on
sudo btmgmt discov no

# Scan 비활성화
sudo hciconfig hci0 noscan 
#OR
sudo btmgmt connectable off
sudo btmgmt discov no

Scan 을 활성화해두면 명령어로 재부팅 전까지 다른 장치의 블루투스 스캔에 응답할 수 있다.


Page Scan(connectable) 은 이미 서로 알고 있는, 즉 페어링된 적이 있는 기기와 연결하는 방식이고

Inquiry Scan(discoverable) 은 서로 모르는 기기가 연결하기 위한 방법이다.

(즉, 처음 연결이 필요할때만 Inquiry Scan 모드를 활성화해주면 된다.)


hciconfig hci0 명령어로 확인해보면 각 PSCAN ISCAN 키워드로 활성화 상태를 알려주고,

btmgmt info 명령어로 확인해본다면 current settings에 discoverable 이 있는지로 Inquiry Scan 활성화 여부를 확인할 수 있다.




3. RFCOMM 실행, 서비스화

RFCOMM 을 통해서 시리얼 연결을 터미널로 연결한다.



#rfcomm watch [dev] [channel] [cmd]
#    watch: listen 과 동일하지만, 자식 프로세스가 종료되거나 클라이언트와 연결이 끊길 경우 다시 listening 시작함.
sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100

이 명령어를 실행하면 다른 장치에서 블루투스로 파이에 연결했을때 터미널로 연결해준다.

특정 계정 자동 로그인을 해주고 싶다면 마지막에  -a <사용자> 를 추가해주자.

sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100 -a pi


이 명령어를 매번 실행해줄 수 없으므로, 이것도 데몬화한다.

/etc/systemd/system/rfcomm.service 파일을 아래와 같이 만들어 준다.



[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch hci0 1 getty rfcomm0 115200 vt100

[Install]
WantedBy=multi-user.target


이후 아래 명령어로 활성화 해주면 끝.



sudo systemctl daemon-reload
sudo systemctl enable rfcomm # 자동실행 활성화
sudo systemctl start rfcomm # 시작



4. Mac 에서 연결

시스템 환경설정 - Bluetooth 에서 검색해서 연결할 수 있다.

일단 연결하면 기기 등록 후 잠깐 연결됨 상태이다가 바로 연결 안 됨 상태로 바뀔텐데 상관없음.



ls /dev/cu.*
(out)/dev/cu.MALS    /dev/cu.SOC    /dev/cu.Bluetooth-Incoming-Port
(out)/dev/cu.[hostname]-SerialPort


이렇게 /dev/cu.[hostname]-SerialPort 장치가 추가되어 있다. 추가가 안되어있다면 SP profile 이 제대로 추가가 안된 상태임.


이 장치를 열면 되는데, screen 으로 열 수 있다.


screen /dev/cu.[hostname]-SerialPort 115200


왜 그런건진 잘 모르겠는데, 이 상태에선 일부 출력(ssh 로그인이라던가..)이 client 의 쉘이 아니라, rfcomm을 실행한 쉘에 출력이 된다.

hyphen 옵션을 주고 다시 로그인해주면 해결됨.

su pi -


윈도우 사이즈도 제대로 반영이 안된다는 것 같은데, 이 경우에는 ssh localhost 로 해결된다고.



5. 다른 장치에서 연결

알아서 블루투스 시리얼 연결을 시도해보자... 일반적으로 많이 하는 SPP 연결방법과 동일해서 레퍼런스가 많을 듯.


윈도우는 모르겠고, 안드로이드에서는 관련 앱이 많을 것이고, iOS 에서는 안되는 것으로 안다.


SPP 말고 다른 프로파일로 어찌 만들어본다면 가능할 것 같긴 한데.. 일단 나는 맥에서만 연결이 되면 되기 때문에 나머진 생략.


참고

https://www.reddit.com/r/raspberry_pi/comments/6nchaj/guide_how_to_establish_bluetooth_serial/

TLS 1.0 은 이제 보안 정책으로 사용이 금지되어 있다.

그래서 기술적으로는 구현이 되어있음에도 불구하고, 브라우저나 각종 라이브러리로 사용을 하려고 하면 오류가 난다.



크롬 기준 이러한 사이트에 접속하려고 하면


The connection to this site uses 

TLS 1.0 (an obsolete protocol), 

RSA (an obsolete key exchange),

3DES_EDE_CBC with HMAC-SHA1 (an obsolete cipher).


이런 메시지를 내면서 접속을 불허한다.




이런 사이트에 대해 Python 을 사용하여 요청을 보낼때 이를 굳이 우회하는 방법.


나의 경우 requests 라이브러리를 사용했는데, urllib3 라이브러리를 사용한다면 동일하다.

urllib3.util.ssl_.DEFAULT_CIPHERS 에 'DES-CBC3-SHA' 을 추가해주면 됨.

콜론으로 구분되기 때문에



urllib3.util.ssl_.DEFAULT_CIPHERS += ':DES-CBC3-SHA'


이렇게 작성해주면 된다.

(DES-CBC3-SHA 과 3DES_EDE_CBC 은 명명법만 다르지 같다고 한다.)


requests 라이브러리를 쓴다면

requests.packages.urllib3 로 임포트 되어 있으니 여기다 해줘도 됨(혹은 여기다가 해줘야만 할 수도?)



requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':DES-CBC3-SHA'


이래도 안되는 경우가 있는데, OpenSSL 문제인 것 같다.

안되는 시스템에서 

$ curl --sslv3 주소

을 해봤을 때,

curl: (4) OpenSSL was built without SSLv3 support

같은 오류가 나온다면 v3을 지원하는 버전으로 재컴파일 하거나 설치해주도록 하자.


Trivial

requests 기준으로 인증서 오류도 날테니 요청을 보낼때 verify=False 인자도 추가해주자.



그리고 이러면 또 warning 이 매번 출력되는데, 아래와 같은 방법으로 비활성화 할 수 있다.

똑같은 코드지만, 상황에 맞게 복붙해서 사용하자.


# urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# requests
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)


참고

https://stackoverflow.com/questions/50707974/force-tls-1-0-connection-with-requests?noredirect=1&lq=1

https://stackoverflow.com/questions/27981545/suppress-insecurerequestwarning-unverified-https-request-is-being-made-in-pytho

나도 잠깐 고생한 적이 있었는데, 원인도 모르고 고생하다 나에게 물어오는 사람이 종종 생겨서,

혹시나 이 글이 검색에 걸려 도움을 받는 사람이 있을까 싶어 남겨본다.


통신사에서 제공하는 무료와이파이나 군부대 사지방 인터넷 등에서 웹서핑을 하면, 대부분의 사이트는 접속이 잘 되지만 특정 서비스들이 안되는 경우가 종종 발생한다.


특정 사이트 자체가 접속이 안되거나,

사이트 접속이 되긴 하는데 특정 기능이 작동을 안하거나,

특정 프로그램이 제대로된 작동을 못하거나.



이 문제들은 모두 공용 와이파이의 보안정책 때문인데, 정확히 확인해보진 않았지만 대충 80/443 포트를 제외하고 IN/OUT 을 다 막는다고 생각하면 된다. (dynamic port 대역은 남겨두려나?)


그래서 간단하게로는 :8080 이라던가, :8888 이라던가, :8443 등등 다른 포트 위에 돌아가는 페이지에 접속을 할 수 없거나,

5900 포트를 사용하는 vnc 등에 접속을 할 수 없다.


우리학교 포탈 시스템이 해당되고, 예전엔 KT 도 그랬던 것 같은데 지금은 아닌 듯.



해결법은 서비스 제공자에게 80/443 포트를 사용하여 서비스 하도록 요청하거나,

공용 와이파이의 정책을 완화해주도록 요청해야할텐데, 둘 다 아무래도 현실성이 떨어지겠지?


그냥 이런 구린 와이파이를 안쓰는게 제일 좋겠지만,

어쩔 수 없다면 80,443 포트를 사용하는 프록시나 openVPN 을 사용하는게 그나마 가능한 해결책일 것 같다.



이런 문제 때문에서인지, 카톡 같은 애들은 소켓을 열 때 80, 443 포트도 후보군에 있다.

서비스를 개발, 제공한다면 고려해보면 좋은 지점.

필요하다 생각만 했는데.. 이제서야 구매. (정작 이제 필요없어진 것 같지만.)


찾아보며 느낀 점이 리뷰나,, 상세 설명 같은게 너무 없다고 생각되어서 작성해봄.

포장 뜯자마자 메뉴들 만져보고 끄적거리는 거라서 실 사용기와는 거리가 멀다고 생각함.




나의 녹음기 용도는

신경 안쓰고 일상에서 녹음을 해뒀다가 후에 확인하기 위한 용도.


따라서 구매 조건은.. 이 게시글과 상당히 흡사했는데 - 보이스레코더 녹음날짜시간 기록여부 궁금합니다.


(뭐.. 모든 조건이 크게 상관없고 '있었으면 좋겠다' 였지만.. 여튼)

1. 날짜시간이 기록될 것 (중요)

2. 배터리 신경 안쓰게 장시간 가능

3. 음성을 감지해서 자동 녹음

4. 유명한 회사가 아니면 구리다고 하니 적당히 유명할 것

5. 클립 형태 같은 느낌으로 옷에 적당히 달고다닐 수 있을 것


제품을 찾다보면 생각보다 조건들에 해당되는게 잘 없다. 특히 1번 날짜시간에서 80% 제품이 걸러지는 느낌?


그리고 메이저 회사를 넘어가면 녹음기 자체가 뭔가 불법적인 상황에 사용되는 느낌으로 제작되어서 하나같이 마음에 안들었음...



여튼 이래저래 타협하고 결국 구매를 결정한 필립스 VTR-7100.

날짜시간이 기록되고 배터리 타임이 길었던게 결정적인 구매 조건.


VTR-8000 이 좀 더 이뻐보이긴 했지만, 녹화 기능이 무슨 증거 채취할게 아니고서야 아무리 생각해도 쓸데 없었고,

가격이 10여만원 가량 더 비싸서 단념했다.



VTR-7100에 대해서 기본적인 내용은 인터넷에 잘 나와 있으니 생략하고,

내 생각과 달랐던? 혹은 아쉬웠던 점들 위주로 적어보겠음.


1. 녹음 타입 / 노이즈 감소

녹음 타입 종류는 PCM, HP(HQ), SP, SLP(LP), LINE-IN 5가지가 있고 기본값은 HP.

HP로 충분히 우수했고, SP는 좀 먹먹한 느낌, SLP는 울리는 소음과 더불어 쓸게 못되는 느낌.


음질이 중요한 상황이 아니라면 SP 정도로 충분한 것 같았다.


녹음 타입에 LINE-IN 이 있던데, aux 선을 연결해서 그 소리를 녹음하는게 가능하다.

인터넷 상에서 찾아볼 땐 못본 것 같아서 한 줄 남겨둠.


라디오 녹음 등의 기능도 제공되던데,, 사실 쓸일 없을 듯?


디지털 노이즈 감소기능을 켜면 녹음 타입은 LINE-IN으로 설정되고, PCM 256kbps 로 녹음된다.

8GB 기준 녹음 가능 시간은 72시간 56분 정도.

(참고로 그냥 PCM 설정시 PCM 768kbps)


그런데.... 노이즈 감소 기능을 켜지 않으면 주변 바람소리 같은 소음?이 꽤나 크게 녹음되는 편이다. (치지지지지지...)

다만 다른 녹음기들도 인터넷에 올라온 영상을 보면 비슷한 것 같다.. 이런 소음을 없애려면 아무래도 마이크가 좀 더 커야겠지..?ㅠ


2. VA(소리 감지 자동 녹음)

제품설명 페이지에는 녹음을 시작하는 VR 레벨을 설정할 수 있다고 나와있는데, 설정 화면을 찾을 수 없다.

설명서에도 적혀있지 않는게, 허위광고(?)인 듯 하다.


그리고 나는 소리가 감지되면 그때그때 녹음 파일을 생성할 줄 알았는데,, 하나의 녹음 파일에 일시정지, 녹음재개를 반복한다.

파일을 들어보면 어느 지점에서 끊기고 다시 녹음되었는지 구분도 안가고,, 중요했던 날짜시간 기록도 무의미해 진다.


어찌보면 제일 중요한 기능 중 하나였는데, 무쓸모한 기능이 되어버렸음.. VR 레벨 설정 기능도 없고...


3. 날짜/시간 기록 방식, 폴더 시스템

알고 있었긴 한데,, 파일시스템 상의 생성/수정일 정보를 이용한다.

하다못해 id3 tag 정도 남겨주길 바랐는데...

파일을 컴퓨터로 가져올 때 주의해야할 듯.


폴더는 VOICE/A,B,C,D 4개 폴더와 MUSIC 폴더로 고정인 듯 하고,

A,B,C,D 각 99개까지 녹음파일이 저장될 수 있다고 한다. (굳이.. 대체 왜....)


4. 전원 스위치와 녹음 스위치

이거 조금 웃기고 복잡한게..

좌측면에 전원 스위치가 있고, 우측면에 녹음 스위치가 있는데,

재생버튼을 꾸욱 눌러서 전원 On/Off 가 또 가능하다....


좌측면 전원 스위치는 master 전원 느낌으로 정말 물리적으로 전원을 끊어버리는 느낌?

이게 꺼져있으면 녹음 스위치를 올려도 녹음이 시작되지 않고, 녹음 중에 끌 경우 파일이 오류나서 저장된다.


즉, 홍보문구 상의 녹음 슬라이더만 올려서 즉시 녹음을 사용하려면...

좌측 전원 슬라이더는 켜두고, 재생버튼을 꾸욱 눌러서 전원을 끈 상태가 전제 조건...


그리고 이 슬라이더가 별로였던게 제공된 파우치에만 넣었는데 스위치가 움직이더라.

이건 좀 어이없었음... 신경써서 넣으면 되긴 한데...


전원 슬라이더가 왜 필요한지 잘 모르겠지만, 굳이 만들어야 했다면 좀 더 구석에 조작이 잘 안되게 만들었으면 어떨까 싶다.


5. 충전

충전포트가 주로 쓰이는 안드로이드 충전용 5핀 micro-usb 가 아니고 mini usb 다...

아쉬운 부분이지만 자주 충전 안해도 되게 충분한 배터리 시간을 뽑아주니 괜찮을 듯


또 충전 중 사용이 불가능하다. 사소하지만 또 마음에 안 든 부분..


6. 기본 제공 외장마이크

왜 외장으로 마이크를 뒀을까... 궁금했는데 그냥 방안에서 테스트 해볼 때는 내장마이크도 충분하게 느껴졌다.

물론 음질이 더 좋은 것 같긴 한데.. 일단은 빼고 사용해 볼 예정.


이어폰을 꼽으면 녹음 중 모니터링이 가능한데, 이 마이크를 꼽으면 이어폰 연결 단자가 막히기 때문에 사용할 수 없게 된다.


쓸만한 마이크가 제공되니 3.5파이 라인 연장선만 있으면 유선 원거리 녹음은 쉬워지려나? ㅋㅋㅋ


7. 무선마이크

이 제품의 특이점이 아닐까 싶은데.... 사실 왜 필요한지 잘 모르겠는 기능이기도 함.


심지어 무선 마이크의 목걸이는 충전선 같은 재질로 탈착이 불가능하다. 아마 안테나 역할을 하는 듯?

본체에도 이어폰을 연결해야 정상적인 사용이 가능하고, 통신 채널은 BAND1, BAND2 2개를 제공하고 내가 선택하게 되어 있다.


무선마이크의 배터리는 7시간 정도 간다고 설명서에 적혀있고 충전은 마찬가지로 mini usb 포트를 사용한다.


크기는 생각보다 크고 음질은 제대로 테스트해보지 않았음.

원거리의 녹음을 껏다켰다하면서 모니터링까지 필요한 상황이 아니면 정말 쓸모 없어 보인다.



8. 기타

1) 스피커는 생각보다 좋은 느낌? 다만 내가 막귀라서.. 그냥 소리도 크고 음질도 괜찮은 것 같았다.


2) 녹음 시작까지 걸리는 시간이 생각보다 길다.

그때그때 좀 편차가 있긴 하던데, 길땐 거의 7~8초 걸리는 느낌? 짧을 땐 2~3초쯤?


제대로 테스트를 해본건 아니지만, 처음 켜지거나 포맷 직후엔 녹음파일 이름을 정하기 위해 스캔하면서 걸리는 시간이 아닐까 싶다.

다만 전체 삭제 직후에 매번 오래걸리는건 좀 아이러니...



총평

날짜시간 기록되는 점을 제하면 뭐하나 생각한대로 작동하는 기능이 없다.

다른 제품이 얼마나 좋은지 잘 모르겠지만... 날짜시간이 중요한게 아니라면 다른걸 사서 쓰는게 어떨까 싶다.


딱히 메리트가 없다고 생각됨.

나도 날짜시간을 포기했어야했나.. 싶기도 하고....


결국 환불함.

티스토리에 Prism 을 적용하였음.

기록용 및 글 작성 참고용.


선택한 옵션 주소는

https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+c+autohotkey+bash+cpp+arduino+django+docker+markup-templating+git+go+http+java+json+kotlin+markdown+makefile+nginx+objectivec+php+sql+python+plsql+swift+vim&plugins=line-highlight+line-numbers+toolbar+remove-initial-line-feed+command-line+copy-to-clipboard


플러그인

Line Hightlight

Line Numbers

Command Line

Copy to Clipboard Button



<pre class="line-numbers" data-start="3" data-line="4-5,8"><code class="language-python">

print('Hello world!')


</code></pre>

<pre class="command-line" data-user="root" data-host="local" data-prompt="PS >"><code class="language-bash">
</code></pre>

<code class="language-bash">~~~</code>

pwd
/usr/home/chris/bin
ls -la
total 2
drwxr-xr-x   2 chris  chris     11 Jan 10 16:48 .
(out)drwxr--r-x  45 chris  chris     92 Feb 14 11:10 ..



<pre><code class="language-bash">

<pre class="command-line" data-prompt="$" data-filter-output="(out)"><code class="language-bash">
<pre class="command-line" data-prompt="$" data-output="1-2"><code class="language-bash">

</code></pre>

+ Recent posts