맥에서 macOS Server로 L2TP VPN 구축

보급형 공유기(ex. iptime)에서 제공하는 VPN은 보통 보안이 취약한 PP2P 프로토콜을 사용한다. 하지만, iOS 10 및 macOS Sierra 에서는 더이상 PP2P 프로토콜을 사용한 VPN 을 접속할 수 없게 되었다. 그렇다고 L2TP VPN 을 지원하는 공유기로 바꾸자니 아깝다. 만일 맥과 macOS Server 앱이 있다면, 손쉽게 L2TP/IPSec 을 이용한 VPN 을 구축할 수 있다.

VPN 설정하기


좌측 메뉴에서 서비스>VPN 을 선택하고, 우측 상단에서 앱을 켠다. 그리고 VPN 호스트 이름과 공유 보안을 채워 넣는다.

VPN 호스트 이름: ‘외부 접속시 사용할 주소’, IP나 DNS를 이용한다.
공유 보안: ‘외부 접속시 사용할 VPN 비밀번호’
클라이언트 주소: 외부 접속한 기기가 사용할 내부 IP
DNS 설정: VPN 에 접속한 기기가 주소검색시 사용할 DNS 서버 주소, macOS Server 앱에 있는 내부 DNS 를 이용해도 상관없다.

공유 보안 키는 특수문자와 대소문자를 포함하여 최대한 복잡하게 설정해야 한다.

VPN 설정은 이것으로 끝이다.

User 만들기


좌측 메뉴에서 계정>사용자 를 선택하고, 하단에서 + 를 누른다.
전체 이름: 안 넣어도 된다.
계정 이름(*중요): VPN 접속시 사용할 ID 이다.
이메일 주소: 생략
암호: VPN 접속시 사용할 암호이다.
확인: 위에서 넣은 암호를 한번 더 입력
홈 폴더: 단순히 VPN 에 접속하기 위한 계정을 만들고 싶은 거라면 “없음 – 서비스전용”을 선택하자. 로그인 창이 지저분해지지 않는다.

생성을 누르면, VPN 접속을 위한 계정 생성이 완료 된다.

공유기 설정

공유기에서 macOS Server 앱이 있는 맥 기기로 포트포워딩을 해준다. L2TP VPN 이 사용하는 포트는 3개이다. UDP1701, UDP500, UDP4500. 포트포워딩 방법은 공유기마다 천차만별이므로 생략한다.

iOS 에서 VPN 접속 테스트

설정한 VPN이 잘 작동하나 간단히 확인해보자.

설정(Settings) 앱에서 일반(General) > VPN 을 선택한 뒤 VPN을 추가(Add VPN Configuration…)한다.

Type : L2TP를 선택한다.
Description: iOS에서 보게 될 공유기 이름이다. 아무거나 넣어도 상관없음.
Server: ‘VPN 설정하기’에서 입력한 ‘VPN 호스트 이름’을 넣는다.
Account: ‘User 만들기’에서 입력한 ‘계정 이름’을 넣는다.
Password: ‘User 만들기’에서 입력한 ‘암호’를 넣는다.
Secret: ‘VPN 설정하기’에서 입력한 ‘공유 보안’을 넣는다.

입력을 마쳤으면 완료를 클릭하고, 연결해본다.

접속이 안될 시

어떤 공유기(ex. netis)들은 L2TP 프로토콜을 차단하는 메뉴를 갖고있다. 공유기가 L2TP 프로토콜을 이용한 VPN 서버를 제공할 수 있는 지와는 전혀 관련이 없다. 그런 공유기라면 차단을 해제해준다.

VPN 서버(맥)를 공유기 자체로 활용하고 있는 게 아닌 이상, Windows 7 이나 Windows 10 에서 공유기 하단에 물린 VPN 서버에 접속하는 게 잘 안될 것이다. 다음 글을 참조한다.

라즈베리파이 node.js로 웹에서 LED 제어

라즈베리파이 에서 node.js 를 활용하여 웹에서 LED 를 제어해보자. Form 태그를 이용해 POST 요청을 받아서 원하는 GPIO 를 ON/OFF 해볼 것이다.

사전준비

웹앱의 구조를 손쉽게 만들기 위해서 express 프레임웍을 활용하자.
$ sudo npm install -g express
$ sudo npm install -g express-generator

코드를 수정한 뒤 서버를 껐다켜기 귀찮으므로, nodemon도 설치하자.
$ sudo npm install -g nodemon

기본설정

설치가 끝나면 express로 프로젝트를 생성한다. --view 옵션을 빼먹는다면 html을 jade로 작성해야 해서 대략 난감할 것이다.
$ express gpio_onoff --view=ejs

$ cd gpio_onoff
$ npm install

LED를 제어하기 위해 필요한 모듈도 설치하자.
$ npm install onoff

nodemon으로 웹서버를 실행하자
$ nodemon

/views/index.ejs 수정

처음 express 프로젝트를 접하면 도대체 무슨 파일을 수정해야 html을 고칠 수 있을까 혼란스러운데, .ejs 파일이 html파일이 된다고 생각하면 된다. 즉, index.ejs가 index.html로 변환되는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
<!-- 추가할 부분 (5줄) -->
    <form action="/onoff" method="POST">
    	ON:<input type="radio" name="LED" value="on">
    	OFF:<input type="radio" name="LED" value="off"></br>
    	<button type="submit">Submit</button>
    </form>
  </body>
</html>

코드를 간단히 설명하면, Submit 버튼을 누르면 localhost:3000/onoff 주소로 POST 요청이 이루어진다. LED라는 이름을 갖는 변수는 웹에서 선택한 2개의 라디오 버튼에 따라서 on이나 off값을 갖게 된다.

localhost:3000/ 에 접속하여

와 같은 그림이 나오는지 확인해보자. 아직, Submit 버튼은 제대로 동작하지 않는다.

/routes/index.js 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var express = require('express');
var router = express.Router();
 
//추가할 부분 (3줄)
var bodyParser = require('body-parser'); // Form 값을 읽어오기 위해 필요
var Gpio = require('onoff').Gpio,
	gpio21 = new Gpio(21, 'out'); // GPIO 21번 사용
 
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
 
//추가할 부분 (8줄)
router.use(bodyParser.urlencoded({extended:true}));
router.post('/onoff', function(req, res, next){
	if (req.body.LED === "on") {
		gpio21.writeSync(1);
	} else {
		gpio21.writeSync(0);
	}
})
 
module.exports = router;

참고로 $ gpio readall 을 통해 GPIO 핀 값들을 읽었을 때 BCM 번호가 onoff 모듈이 사용하는 번호이다. 예제에서 사용한 21번 GPIO는 라즈베리파이 3 버전에서 제일 우측 하단에 위치해 있고, 이름은 GPIO.29 이다.

코드를 간단히 설명하면, /onoff 주소로 POST 요청이 오게되면, 조건문을 실행한다. Form 에서 입력받은 LED 값이 on 이라면 GPIO 21을 켜고, 입력받은 LED 값이 off라면 GPIO 21을 끄는 것이다.

다 되었다.

결과 확인

http://localhost:3000 을 새로고침하여 확인해보자.

이걸 반복하면 다음과 같은 웹페이지도 만들 수 있다.

Rasbian 에서 node 깔끔하게 삭제하고 재설치하기

라즈베리파이의 운영체제인 라즈비안(Rasbian)에서 node를 깔끔하게 삭제하고 재설치 해보자. node를 지우기 위해서 find 명령어를 통해 일일이 모든 폴더를 찾아다니면서 node와 npm을 삭제할 수도 있지만 매우 귀찮다. 또한 마구마구 지우다가 잘못 지워버리지 않을지 걱정이 되기도 한다. 하지만, 라즈비안에서는 apt-get 을 이용하면 간단하게 재설치할 수 있다. (맥에서 역시 homebrew가 아닌 apt-get을 이용해서 설치했었다면, 같은 방법으로 적용할 수 있다.)

먼저 https://nodejs.org/ 에 접속해서 최신 버전을 확인 한 뒤, 설치되어 있는 최신 버전을 확인한다.

$ node -v

최신버전이 아니라면, 먼저 apt-get 앱을 최신버전으로 업데이트 해준다.

$sudo apt-get update
$sudo apt-get upgrade

설치되어있는 nodejs 관련 파일을 모두 삭제한다.
$ sudo apt-get purge nodejs*

만일 잘 삭제되었는지 확인하고 싶다면 다음 명령어를 치고 오류가 나는지 확인한다.
$ node
bash: /usr/bin/node: No such file or directory

curl 명령어를 통해 node의 최신 버전을 받아온 뒤(2017년 12월 현재 9버전, 만일 버전이 바뀌었거나, 구 버전을 설치하고 싶다면 숫자만 바꾸면 된다.)
$ curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash –

다운이 완료되면 친절하게 다음 명령어를 알려준다.
$ sudo apt-get install -y nodejs

설치가 완료되면 버전을 확인해보자.
$ node -v
$ npm -v

참고로, node 의 최신버전이 9라고 해서 npm 도 9가 최신인 것은 아니다.

그런데, rasbian 에서 node를 설치했을 경우, npm 에서 전역(global) 설치가 안먹는 경우가 있다.

$ sudo npm install -g express

와 같이 설치했을 경우, Error: EACCES: permission denied 와 함께 수십줄의 에러메세지가 나타난다면

Rasbian 에서 npm Error: EACCES: permission denied를 참조한다.

Rasbian 에서 npm Error: EACCES: permission denied

라즈베리파이의 운영체제인 라즈비안(rasbian)에서 전역 옵션(-g)을 통해 모듈을 설치했을 때, Error: EACCES: permission denied 메세지와 함께 수십줄의 에러코드가 뜨면서 제대로 설치가 되지 않을 때가 있다.

예를들어

$ sudo npm install -g onoff

와 같이 전역으로 설치했을 때, 각종 권한문제로 설치가 되지 않는 것이다. 이 문제는 전역 옵션으로 모듈이 설치될 폴더의 권한을 갖고 있지 못했기 때문에 발생한다. 우선, rasbian 에서 node 깔끔하게 삭제하고 재설치하기를 참조하여 재설치해보는 것을 추천하고 그래도 되지 않을 경우 아래와 같은 순서로 진행해본다.

먼저 npm 의 설정파일을 확인한다.
$ npm config get prefix

아마 /usr 라고 뜰 것이다. /usr라고 뜰 경우, 새 폴더를 생성해서 $PATH도 설정해주고 npm 의 설정파일도 변경하여 해결해야하는 것으로 알려져 있는데, 딱히 그렇게 하지 않아도 되는 것 같다. /usr 라고 뜰 경우에, 전역 옵션의 모듈이 설치되는 곳은

/usr/lib/node_modules/.. 이다.

그러므로 이 폴더에 권한을 부여한다.

$ sudo chown -R 아이디 /usr/lib/node_modules

만일 이 폴더가 없다면

$ cd /usr/lib
$ mkdir node_modules

를 통해 폴더를 생성한 뒤에 chown 명령을 진행한다. 권한을 부여한 뒤 다시 한번 전역 설치를 실행해본다.

$ sudo npm install -g 모듈이름

만일 에러 없이 잘 깔렸다면, 다음의 명령어로 확인해본다.

$ npm ls -g --depth=0

/usr/lib
├── express@4.16.2
├── express-generator@4.15.5
├── npm@5.5.1
└── onoff@1.1.8

와 같이 뜨면 잘 설치된 것이다.