* 사업 등 관련 문의: T) 02-322-4688, F) 02-322-4646, E) info@wikisecurity.net

Openvpn으로 자신의 IP를 숨기는 간단한 프로그램(golang)

* 자기 IP를 숨기려는 목적은 여러 가지가 있다.
- 구글이 중국에서 철수 했을때도 Public VPN을 이용하여 차단만을 우회하는 중국인들도 많았고
- Red Team으로 구성된 Real PT를 수행하기 위해 불가피하게 자신의 IP를 숨겨야 하는 상황도 있고
- 보안 취약점 진단을 하면서 Block된 자신을 IP를 우회하기 위해 사용되기도 하며
- 간단한 보안 시스템을 개발한 후 서로 다른 Source IP로 테스트하기 위한 목적으로 도 사용되고
- 최근 유행하는 게임인 포켓몬 게임의 Fake GPS와 같이 자신의 물리적 위치를 속이기 위해 사용하기도 하고
(지금 CN에서는 총동원령이 내려지고 데놓고 공격하겠다고 하는데.. 우리는 집안싸움이나 하고 개나소나 대장하겠다고 서로 삿대질이나 하고 있다.. 참 한심하다~)

* 자기 IP를 숨기는 방법도 여러 가지가 있다.
- 목적지가 내부망이 아닌 인터넷망이라면 여러가지 방법이 있고 이를 상업적으로 제공하는 회사들도 있으나 중요한 것은 목적에 따라 어떤 방법을 선택하느냐하는 것이다.
- Open 또는 Private Proxy Server를 이용하는 방법
- Cloud Server 또는 Open Shell Server를 이용하는 방법
- Open 또는 Private VPN을 이용하는 방법

* 이번에 소개할 방법은 Open VPN을 이용한 방법이다.
- 자기 IP를 숨기는 방법중에 비교적 안전성을 보장받을 수 있는 VPN을 이용하는 방법이다.
- 전세계 봉사자들에 의해 약 6,000여개의 Public VPN Proxy Server목록을 업데이트하는 VPN Gate를 이용하는 방법이다.
- 환경설정을 통해 이 Public VPN Realy Server에 직접 접속하여 사용하는 방법도 있지만(http://www.vpngate.net/en/ 참조)
- 소스를 보면 알겠지만 vpngate에서는 VPN Relay Server 정보를 손쉽게 가져올수 있도록 api를 제공하고 있다.
- autovpn은 이 api를 이용하며 구글이 만든 개발언어 go로 만들어졌는데, 일부분 수정해서 돌려봤다.(소스는 문서 아래 참조)
(음.. 그러니깐, golang 이랑 openvpn이 설치되어 있어야 한다)

* 수정한 소스코드(autovpn.go)는 아래와 같이 간단하다.

 // autovpn.go
 //
 package main
 
 import (
 	"bufio"
 	"encoding/base64"
 	"fmt"
 	"io/ioutil"
 	"net/http"
 	"os"
 	"os/exec"
 	"os/signal"
 	"strings"
 	"syscall"
 )
 
 func check(e error) {
 	if e != nil {
 		panic(e)
 	}
 }
 
 func main() {
 	chosenCountry := "US"
 	if len(os.Args) > 1 && len(os.Args[1]) == 2 {
 		chosenCountry = os.Args[1]
 	}
 	URL := "http://www.vpngate.net/api/iphone/"
 
 	fmt.Printf("=> getting server list\n")
 	response, err := http.Get(URL)
 	check(err)
 
 	defer response.Body.Close()
 	scanner := bufio.NewScanner(response.Body)
 
 	fmt.Printf("=> parsing response\n")
 	   
 	counter := 0
 	for scanner.Scan() {
 		if counter <= 1 {
 			counter++
 			continue
 		}
 		splits := strings.Split(scanner.Text(), ",")
 		if len(splits) < 15 {
 			break
 		}
 
                hostname := splits[0]
                country_long := splits[5]
 		country := splits[6]
 		conf, err := base64.StdEncoding.DecodeString(splits[14])
 		if err != nil || chosenCountry != country {
 			continue
 		}
 
 		fmt.Printf("=> writing config file\n")
 		err = ioutil.WriteFile("/tmp/openvpnconf", conf, 0664)
 		check(err)
 		fmt.Printf("=> lokking for %s(%s)...Server:%s\n", chosenCountry, country_long, hostname)
 
 		cmd := exec.Command("sudo", "openvpn", "/tmp/openvpnconf")
 		cmd.Stdout = os.Stdout
 
 		c := make(chan os.Signal, 2)
 		signal.Notify(c, os.Interrupt, syscall.SIGTERM)
 		go func() {
 			<-c
 			cmd.Process.Kill()
 		}()
 
 		cmd.Start()
 		cmd.Wait()
 
 		fmt.Printf("=> try another VPN Server? (y/n) ")
 		var input string
 		fmt.Scanln(&input)
 		if strings.ToLower(input) == "n" {
 			os.Exit(0)
 		}
 	}
 }

- 우선 필요한 패키지 설치가 필요하다.(이미 있다면 pass)

 $ sudo apt-get install golang
 $ sudo apt-get install openvpn

- 그리고 받은 autovpn 소스를 컴파일을 한다.

 $ go build autovpn.go

- 이제 아래와 같이 실행하면, (파라메터로 받은 국가 도메인의 Public VPN Relay Server으로 접속)

 $ ./autovpn TH  <= 태국


* autovpn을 실행이전과 이후의 스크린샷
- autovpn 실행이전에는 network interface와 라우팅 테이블이 아래와 같이 2개뿐이다.


- autovpn 실행이후에는 tun0라는 NW interface가 하나 추가되었고, 라운팅 테이불도 설정한 태국의 VPN Relay Server로 P2P Trunneling을 만들었다.

(*) 자~~ 이제 TH이름으로 CN으로 go go~~~~ move~ move~~