60.Unix2008. 11. 7. 10:03
반응형

Solaris 10 에서 openvpn 서버 설치하기


최근 solaris 환경에 openvpn 서버를 설치할 기회가 있었는데, linux 에서와는 달리 약간의 삽질이 필요했습니다. 배포본으로부터 바이너리 및 설치 스크립트를 제공받을 수 없어서, /dev/tun 장치 파일 생성이나 ip forwarding / NAT 설정에서 조금 메모해 둘 필요가 있다고 생각되어 아래 내용을 보충해 둡니다.

작업했던 환경은 solaris 10 입니다. solaris 9 이하에서도 ip filter 설치 이외에 특별한 차이는 없습니다.
# uname -a
SunOS tomoko 5.10 Generic_127127-11 sun4v sparc SUNW,SPARC-Enterprise-T5220 Solaris

openvpn 바이너리 및 tun 드라이버 생성


본문의 [http]1.4.1 설치하기 에 해당되는 내용입니다.

우선 openvpn 소스코드에서 컴파일하지 않으면 되지 않으므로, http://www.sunfreeware.com/ 에서 gcc, libtool 등을 설치하여 기본적인 컴파일 환경을 갖추어야 합니다. 또한 openvpn 컴파일시에 필요한 openssl, lzo 라이브러리도 미리 설치해 두기로 합니다. 각 패키지가 동작하기 위한 의존성이 걸린 패키지도 설치되어 있지 않다면 함께 설치해 주세요.
# gzip -d gcc-3.4.6-sol10-sparc-local.gz
# pkgadd -d ./gcc-3.4.6-sol10-sparc-local
...
# pkgadd -d ./openssl-0.9.8h-sol10-sparc-local
# pkgadd -d ./lzo-2.03-sol10-sparc-local

이제 openvpn 소스코드를 컴파일하게 되는데, solaris 10 에는 /dev/tun 장치가 생성되어 있지 않으므로, 그냥 진행하면 아래와 같은 오류를 내면서 컴파일이 중단됩니다.
tun.c:1183:2: #error I need the symbol TUNNEWPPA from net/if_tun.h
tun.c: In function `open_tun':
tun.c:1245: error: `TUNNEWPPA' undeclared (first use in this function)
tun.c:1245: error: (Each undeclared identifier is reported only once
tun.c:1245: error: for each function it appears in.)
make[1]: *** [tun.o] Error 1
make[1]: Leaving directory `/data/pkg/openvpn/openvpn-2.0.9'

따라서 openvpn 설치 전에 미리 tun 드라이버를 생성해 둡니다. solaris 설치 시디에서 드라이버를 설치할 수 있을 것 같기도 한데, 귀찮기도 하거니와 방법도 잘 모르겠고 해서 구글링한 결과, 아래와 같은 해결책을 찾았습니다.

# wget http://vtun.sourceforge.net/tun/tun-1.1.tar.gz
# zcat tun-1.1.tar.gz | tar xvf -
# cd tun-1.1/solaris
# perl -pi~ -e 's;"TUN/TAP driver .*;"TUN/TAP driver 1.1",;' tun.c
# perl -pi~ -e 's/#define TUNSETPPA.*/$&\n\n#define TUN_VER "1.1"/' if_tun.h
# gcc -O2 -Wall -D_KERNEL -I. -m64 -mcpu=ultrasparc -c tun.c
# /usr/ccs/bin/ld -r -o tun tun.o
# file tun
tun:            ELF 64-bit MSB relocatable SPARCV9 Version 1, UltraSPARC1 Extensions Required
# cp tun /usr/kernel/drv/sparcv9/tun
# cp tun.conf /usr/kernel/drv/tun.conf
# cp if_tun.h /usr/include/net/if_tun.h
# chmod 755 /usr/kernel/drv/sparcv9/tun
# chown root:sys /usr/kernel/drv/sparcv9/tun /usr/kernel/drv/tun.conf
# chown root:bin /usr/include/net/if_tun.h
# rem_drv tun
# add_drv -v tun
# ls -als /dev/tun
1 lrwxrwxrwx 1 root sys 29 Oct 22 11:03 /dev/tun -> ../devices/pseudo/clone@0:tun

사용하는 장비의 아키텍처에 따라 gcc 옵션 및 tun 드라이버 설치 위치를 적절히 변경하면 되겠습니다. 제대로 되었다면 /dev/tun 캐릭터 디바이스가 생성됩니다.

다음으로 openvpn 소스코드 컴파일입니다. openssl 및 lzo 라이브러리 위치를 지정해 줄 필요가 있습니다. 아마도 LD_LIBRARY_PATH 에도 지정이 되어 있어야 할 것 같습니다. (귀찮아서 미확인)
# env | grep PATH
LD_LIBRARY_PATH=/usr/local/lib:/usr/local/ora:/usr/local/ssl/lib:/usr/openwin/lib:...
PATH=/usr/local/bin:/usr/local/ssl/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/ccs/bin:...
# ./configure --with-ssl-headers=/usr/local/ssl/include --with-ssl-lib=/usr/local/ssl/lib
# make
# make install
# ls -als /usr/local/sbin/openvpn
1504 -rwxr-xr-x 1 root root 1525160 Oct 22 14:57 /usr/local/sbin/openvpn

openvpn 기동시에 LD_LIBRARY_PATH 지정하는 것이 귀찮다면, 바이너리를 링크할 때 rpath 지정해 주면 편리합니다. solaris ld 는 rpath 지정하는 옵션이 -R 입니다. rpath 지정하는 것이 나쁘다는 의견도 있으므로 아래는 참고로 하시면 되겠습니다.
# gcc  -g -O2  -L/usr/local/ssl/lib -R /usr/local/lib:/usr/local/ssl/lib -o openvpn            \
    base64.o buffer.o  crypto.o error.o event.o  fdmisc.o forward.o fragment.o  gremlin.o      \
    helper.o init.o  interval.o list.o lzo.o  manage.o mbuf.o misc.o  mroute.o mss.o mtcp.o    \
    mtu.o  mudp.o multi.o ntlm.o occ.o  openvpn.o options.o otime.o  packet_id.o perf.o ping.o \
    plugin.o pool.o proto.o  proxy.o push.o reliable.o  route.o schedule.o session_id.o        \
    shaper.o sig.o socket.o  socks.o ssl.o status.o  thread.o tun.o                            \
    -lssl -lcrypto -llzo2 -lnsl -lsocket
# env | grep LD_LIBRARY_PATH
(nothing found)
# ldd openvpn
        libssl.so.0.9.8 =>       /usr/local/ssl/lib/libssl.so.0.9.8
        libcrypto.so.0.9.8 =>    /usr/local/ssl/lib/libcrypto.so.0.9.8
        liblzo2.so.2 =>  /usr/local/lib/liblzo2.so.2
        libnsl.so.1 =>   /lib/libnsl.so.1
        libsocket.so.1 =>        /lib/libsocket.so.1
        libc.so.1 =>     /lib/libc.so.1
        libdl.so.1 =>    /lib/libdl.so.1
        libgcc_s.so.1 =>         /usr/local/lib/libgcc_s.so.1
        libmp.so.2 =>    /lib/libmp.so.2
        libmd.so.1 =>    /lib/libmd.so.1
        libscf.so.1 =>   /lib/libscf.so.1
        libdoor.so.1 =>  /lib/libdoor.so.1
        libuutil.so.1 =>         /lib/libuutil.so.1
        libgen.so.1 =>   /lib/libgen.so.1
        libm.so.2 =>     /lib/libm.so.2
        /platform/SUNW,SPARC-Enterprise-T5220/lib/libc_psr.so.1
        /platform/SUNW,SPARC-Enterprise-T5220/lib/libmd_psr.so.1

ip forwarding / NAT 설정


본문의 [http]1.6.2 서버쪽의 다른 서버들 연결하기 에 해당하는 내용입니다.

solaris 10 을 기준으로 설명합니다. solaris 9 이하에서는 설정을 위한 명령어가 약간 차이가 있습니다.

ip forwarding 기능을 활성화 하기 위하여 routeadm 명령을 사용합니다. -u 옵션으로 다음 부팅시에도 적용되도록 된다고 합니다. (미확인)
# routeadm -u -e ipv4-forwarding
# routeadm
              Configuration   Current              Current
                     Option   Configuration        System State
---------------------------------------------------------------
               IPv4 routing   disabled             disabled
               IPv6 routing   disabled             disabled
            IPv4 forwarding   enabled              enabled
            IPv6 forwarding   disabled             disabled

           Routing services   "route:default ripng:default"
...
# ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
        inet 127.0.0.1 netmask ff000000
tun0: flags=10011008d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST,ROUTER,IPv4,FIXEDMTU> mtu 1500 index 3
        inet 10.8.0.1 --> 10.8.0.2 netmask ffffffff
        ether 0
e1000g0: flags=1100843<UP,BROADCAST,RUNNING,MULTICAST,ROUTER,IPv4> mtu 1500 index 5
        inet 210.103.xxx.xxx netmask fffffffc broadcast 210.103.xxx.xxx
        ether xx:xx:xx:xx:xx:xx

tun0, e1000g0 인터페이스 상태에 ROUTER 가 추가되었습니다. 상기 설정으로 openvpn 서버는 라우터의 역할을 하게 되고, openvpn 클라이언트로부터 tun0 를 통해 전달받은 패킷을 외부로 뿌려줄 수 있게 됩니다. 하지만 패킷의 source ip 가 openvpn 클라이언트의 사설 ip 인 상태이므로, 클라이언트가 vpn 을 통해 다른 서버와 통신할 수는 없습니다. 따라서 추가적으로 NAT 설정을 해 주어야 합니다.

linux 의 iptables 에 대응하여 solaris 에는 ip filter 가 있습니다. solaris 10 부터는 기본적으로 설치되어 있고, solaris 9 이하에서는 별도로 설치해야 합니다. 설치 방법은 어렵지 않다고 하니 구글의 도움을 받도록 합시다. 설치가 되었다면 nat 설정을 추가하고(ipnat.conf), 설정을 적용할 네트웍 디바이스를 지정합니다(pfil.ap). ipf 설정은 보다 복잡하게 할 수 있지만, 여기서는 openvpn 클라이언트의 주소지(10.8.0.0/24)에서 들어온 패킷을 외부 인터넷(e1000g)으로 연결하도록 간단하게 한 줄만 추가합니다.
# echo "map e1000g0 10.8.0.0/24 -> 0/32" >> /etc/ipf/ipnat.conf
# echo "e1000g -1 0 pfil" >> /etc/ipf/pfil.ap
# ifconfig e1000g0 down
# ifconfig e1000g0 unplumb
# ifconfig e1000g0 plumb
# ifconfig e1000g0 210.103.xxx.xxx netmask 255.255.255.252 up

pfil.ap 설정을 적용하기 위해서는 네트웍 디바이스를 내렸다 올려야 함에 유의하고, 여기까지 되었다면 pfil, ipfilter 서비스를 구동하여 상태를 확인합니다.
# svcadm enable svc:/network/pfil
# svcadm enable svc:/network/ipfilter
# ipf -V
ipf: IP Filter: v4.1.9 (592)
Kernel: IP Filter: v4.1.9
Running: yes
Log Flags: 0 = none set
Default: pass all, Logging: available
Active list: 0
Feature mask: 0x107

openvpn 클라이언트에서 인터넷을 접속할 때 vpn 서버의 ip 가 묻어 나가는 것이 확인되면 완료입니다. :-)
Posted by 1010