안드로이드는 여러가지 네트워크 디바이스들과의 통신을 지원한다. 과연 이들 과의 통신을 위해 어떻게 관리하고 유지하는지 설명한다.
네트워크 연결 상태 확인
안드로이드의 디바이스를 관리하는 주 목적은 다음과 같다.
네트워크에 연결할 디바이스 선택
다른 시스템도 동일하지만 안드로이드에서는 멀티 포트에 대한 라우팅을 지원하지 않는 관계로 인터넷과 접속하려면 디폴트 라우팅 경로 하나만을 설정하게 된다. 안드로이드는 와이파이로 접속하면 무선 이동통신 데이터 네트워크는 끊어지게 된다.
그 역으로 무선 이동통신 데이터 네트워크로 접속하면 와이파이 망은 끊어지게 된다. 사용자의 선택에 따라 자신의 애플리케이션이 선호하는 망에만 접속하도록 만들 필요가 있다.
네트워크 이상 점검
'네트워크가 접속되었다 끊어졌다' 하는 현상을 모니터링하고 그 원인에 따라 적절하게 사용자에게 알리고 필요한 조치를 하는 방법등이 필요하다.
보안 서비스
보안을 위해 여러가지 기능들이 추가되어야 한다.
인터넷 서비스를 받으려면 두 가지 조건을 만족해야 한다.
- 'IP 주소를 부여받아야 한다.'
- 무선 이동통신 포트나 와이파이를 갖고 있다 하더라도 IP 주소를 부여받지 못하면 인터넷 서비스를 받지 못한다. 원본 안드로이드는 DHCP 를 통해서만 IP 주소를 설정하게 되어 있다.
- '디폴트 라우트로 설정되어 있어야 한다.'
- 두 개 이상의 디바이스가 네트워크로 연결되어 있다 하더라도 인터넷 망과 연결되는 포트는 반드시 디폴트 라우팅 경로와 게이트웨이가 설정되어 있어야 한다.
ConnectivityManager
안드로이드가 제공하는 클래스로 네트워크의 상태를 알 수 있다. 상태 변화가 생기면, 사용자에게 변화된 사실을 알리게 된다.
ConnectivityManager 클래스의 주요 기능은 아래와 같다.
- 와이파이, 2G 나 3G 네트워크 망(GPRS, UMTS)의 네트워크 연결을 모니터링한다.
- 네트워크 연결에 변화가 생겼을 때 브로드캐스트 인텐트를 보내게 된다.
- 네트워크의 연결이 끊어지면 Fail-Over 하여 다른 네트워크망으로 접속하게 된다.
- 네트워크 정보를 제공한다.
안드로이드에서의 WIFI 관리는 다른 문서를 참고한다.
테더링과 애드혹 서비스
테더링은 IP 마스커레이드를 이용한 기능으로서, 두개의 네트워크 인터페이스를 사용하여 한쪽에서 받은 데이터를 다른 한쪽의 네트워크 인터페이스로 보내주는(forwarding) 기술이다.
흔히 3G 와 WiFi 가 지원되는 스마트 폰에서 많이 사용하는 기능 중 하나다.
3G 로 받은 데이터를 Wi-Fi 에 연결된 디바이스로 보낸다던지, 반대로 Wi-Fi 로 연결된 다른 디바이스로 부터 데이터를 받아 3G 네트워크로 보내는 것이 가능해진다.
이제부터 테더링을 위해서 필요한 것들에 대해 알아보고 설명하겠다. 먼저 커널 컴파일 옵션에서 Netfilter 와 NAT 를 선택하여 지원하도록 해야 한다. 직접 커널 컴파일을 하는 방법이 가장 확실하겠지만, 그전에 현재 커널이 이들 기능을 지원하는지 확인해볼 필요가 있겠다.
/proc 디렉토리 내 파일 존재로 확인하는 방법
만약 커널에서 netfilter 가 컴파일되어 있다면, 아래 '/proc' 라고 하는 디렉토리 내에 'net/ip_tables_targets' 파일을 갖게 된다. 물론 컴파일 조건을 모듈(M)로 선택한 경우는 해당 모듈을 올려야 '/proc' 디렉토리 내 파일들로 나타나게 된다.
/proc/config.gz 내부 컴파일 옵션으로 확인하는 방법
커널 버전 2.6 부터 컴파일 조건으로 '/proc/config.gz' 와 같이 설정파일로 보관하는 방법을 제공하고 있다. 해당 파일이 존재한다면 커널이 어떻게 컴파일되어 있는지 확인 할 수 있다.
아래와 같은 커널 컴파일 옵션들이 존재 여부에 따라 Netfilter 라는 패키지와 패키지가 제공하는 기능들이 커널 내 컴파일되었는지 확인할 수 있다.
- CONFIG_NETFILTER=y or m : Netfilter 설치 컴파일 옵션이다.
- CONFIG_IP_NF_IPTABLES=y or m : 패킷들을 차단하거나 또는 NAT 기능을 제공하는 iptables 기능을 설치하는 옵션이다.
- CONFIG_NETFILTER_XT_MATCH_MAC=y or m : 화이트리스트나 블랙리스트와 연결하여 패킷을 차단하는 기능을 설치하는 옵션이다.
패킷 포워딩
안드로이드와 같은 단말기나 PC 는 기본적으로 패킷 포워딩 서비스를 하지 않는다. 패킷 포워딩이란 주로 게이트웨이나 라우터와 같이 패킷을 수신하였으나 해당 패킷의 최종 목적지가 자신의 시스템이 아닌 경우, 네트워크 디바이스를 통해 해당 패킷을 다시 전송하는 기능이다.
만약 안드로이드나 리눅스에서 패킷 포워딩 기능을 설정되어 있지 않다면 자신이 최종 목적지가 아닌 패킷들은 모두 삭제 처리한다. 테더링 서비스를 받고자 하는 주변기기들 입장에서 안드로이드폰이 하나의 게이트웨어 역할을 수행해야 하기 때문에 기본적으로 패킷 포워딩 서비스가 지원되어야 주변기기들이 인터넷 서비스를 받을 수 있다.
안드로이드 패킷 포워딩 기능은 '/proc/sys/net/ipv4/ip_forward' 파일에 '1로 설정함'으로서 실행된다.
DNS & DHCP 서버 구축
에드혹으로 연결된 클라이언트 단말기가 인터넷을 사용하기 위해서는 IP 주소를 설정하거나 또는 배정받아야 한다. 안드로이드가 무선접속장치에 연결되면 자동으로 IP 주소와 게이트 웨이 IP 주소 그리고 DNS 서버의 IP 주소를 할당받는 것처럼 단말기(또는 클라이언트) 역시 동일하게 안드로이드와 에드혹 망으로 연결되자마자 IP 주소를 부여받는 방법을 사용하는 것이 좋다.
이러한 기능을 일명 DHCP 라고 불리는 기능으로 특정 네트워크 그룹 내에 IP 주소를 중앙에서 관리하고 할당할 수 있는 프로토콜을 사용하여 IP 주소를 공급하는 기능을 말한다.
안드로이드 내 기본 애플리케이션으로 이러한 기능을 제공하지 않기 때문에 안드로이드에서 IP 주소를 단말기에게 제공하기 위해서는 DHCP 서버의 기능을 수행하는 애플리케이션 또는 프로그램을 설치해야 한다.
일반서버나 무선 접속장치에서 많이 사용하는 버클리에서 만든 dhcpd 를 사용할 수 있지만, 스마트폰의 규모에 맞게 다소 모듈 사이즈가 작고 활용도가 많은 dnsmasq 라고 하는 데몬을 여기서 사용한다.
dnsmasq 라는 프로그램은 리눅스에서 제공되는 프로그램으로 DNS Cache Server 기능과 DHCP Server 기능을 동시에 제공한다. 테더링 서비스를 주변기기에 제공한다면, 단순히 DHCP 기능만 제공하여도 무방하다. 그러나 DNS 캐시 기능을 활요하면 네트워크의 대역폭을 일정부분 확보할 수 있는 장점도 존재한다.
dnsmasq 라는 데몬을 실행시키기 위해서는 DHCP 와 DNS 정보를 가질 수 있도록 아래와 같은 파일을 제공해주어야 한다.
DHCP 정보 파일
DHCP 정보는 단말기에 제공할 IP 주소와 게이트웨이 IP 주소를 이야기하는 데, dnsmasq 의 dnsmasq.conf 라는 설정파일에 보관한다. dnsmasq 나 dnsmasq.conf 는 안드로이드에서 제공하는 데몬이나 파일이 아니므로 자체 애플리케이션의 /raw 디렉토리 내에 dnsmasq 와 함께 dnsmasq_conf 를 제공하게 된다.
DNS 정보 파일
앞에서 생성한 디렉토리 /conf 내에 resolv.conf 파일을 생성하고 안드로이드의 프로퍼티 정보를 읽어 resolv.conf 에 복사하여 만들어주게 된다.
DHCP 서비스
dnsmasq 데몬이 DHCP 서버 기능을 수행하려면 dnsmasq.conf 파일의 내용을 아래와 같이 설정해 주어야 한다.
dhcp-authoritative ------ 1 dhcp-range=192.168.2.100,192.168.2.105,12h ----------- 2 dhcp-leasefile=/data/data/android.tether/var/dnsmasq.leases ------------ 3 pid-file=/data/data/android.tether/var/dnsmasq.pid ----------- 4 dhcp-option=3,1.2.3.4 -------------- 5 user=root ------------- 6
- dhcp-authoritative : “dnsmasq 가 dhcp 서버로 사용한다”는 것을 선언한다.
- dhcp-range : dhcp 서버로서 클라이언트에게 제공하는 IP 의 범위이다. 위의 설정은 사설 IP 주소 192.168.2.100 에서 192.168.2.105 까지 사용하며, IP 주소를 제공하는 시간은 12시간으로 정한 것을 의미한다. 클라이언트는 12시간 이후 새로운 IP 주소를 DHCP 서버로 부터 다시 할당 받아야 한다.
- dhcp-leasefile : dhcp 서버는 어떤 IP 주소를 어떤 단말기에 제공하였는지 필요한 정보를 보관하게 된다. 이 때 보관하는 장소를 가리키는 설정문이다.
- pid-file : dnsmasq 데몬의 PID 값을 어느 경로에 어떤 파일이름으로 보관할 것인지 정하는 설정문이다.
- dhcp-option : 게이트웨이에 대한 정보 설정은 dhcp-option=3,192.168.1.254 와 같이 하였다. 여기서 dhcp-option=3 의 3은 RFC 2132 규정에 따라 라우터를 의미한다. 만약 보기에 불편하다면 아래와 같이 option 이라는 지시자와 함께 게이트웨이 또는 라우터를 표시할 수 있다. 'dhcp-option=option:router,192.168.1.254' 이 표현은 DHCP 에서 IP 주소를 받는 단말기는 “단말기의 게이트웨이로 192.168.1.254 로 설정하라”는 의미가 된다. 여기서 192.168.1.254 는 단말기들과 에드혹 망을 구성하는 안드로이드폰 디바이스의 IP 주소이기도 하다.
- user : user 는 dnsmasq 사용자를 의미하는데 일반적으로 'user=root' 선언하여 dnsmasq 프로세스를 루트 권한으로 사용하게 된다.
와이파이 에드혹(ad-hoc) 설정
안드로이드폰의 와이파이를 애드혹 모드로 변경시키기 위해서는 제조사의 칩셋 하드웨어와 지원하는 드라이브 그리고 wpa_supplicant 소프트웨어 간에 제대로 된 결합이 이루어져야 한다. 원리는 간단하지만 와이파이 칩셋 제조사나 모델별로 복잡하다.
이중 가장 골치 아픈 부분이 드라이버인데, 드라이버에서 에드혹을 지원할 수 있도록 설정해야 와이파이가 에드혹 모드로 실행하게 된다. 와이파이의 경우, 칩셋 제조사별로 제공되는 모델이 워낙 다양하기 때문에 와이파이 드라이브의 구분없이 일괄적으로 두 가지 방법을 모두 적용시키게 된다.
- iwconfig 를 사용하여 “iwconfig <와이파이 인터페이스> mode ad-hoc” 명령어를 주어 변경하는 방법이 있다.
- wpa_supplicant 의 설정파일에서 에드혹 모드로 설정함으로써 변경시키는 방법이 있다. 정확하게 이야기하면, 와이파이에 에드혹을 적용시키는 방법은 모델별로 사용하는 드라이브에 따라 구분된다. 즉, 원칙대로라면, 어떤 드라이브는 1번 방법을 사용해야 하고 어떤 드라이브는 2번 방법을 사용해야한다. 그러나 그렇게 하면 프로그램이 복잡해지므로 모델과 드라이버의 구분없이 2가지 방법을 모두 사용하여 적용시키게 된다.
Netfilter 패키지 설정
Netfilter 는 ISO 통신의 7계층 중에서 3계층인 네트워크 계층에서 패킷을 차단하는 네트워크 방화벽 기능과 IP 주소를 변경시키는 NAT 라고 하는 네트워크 주소변환 기능을 수행하는 소프트웨어이다.
사설 IP 주소를 사용하는 단말기에서 인터넷 서비스를 받고자 한다면 공중망에서 사용하는 공인 IP 로 전환해야 하는데 그 역할을 수행하는 기능을 하는 것이 바로 Netfilter 의 NAT 기능이다.
Netfilter 는 그 외에도 패킷 차단과 같이 방화벽 기능을 제공한다. 이 기능을 이용하면 원하지않는 패킷들이 내 스마트폰으로 유입되는 것을 차단할 수 있으며, 또한 3G 무선 데이터 네트워크에 접속하지 못하게 차단한다든가 그리고 와이파이를 우선 접속할 수 있게 만든다든가 하는 기능을 수행할 수 있다.
iptables 명령어
Netfilter 를 적용하고자 한다면, iptables 라는 명령어를 사용하는데 iptables 명령어는 테이블, 체인 그리고 규칙으로 구성되어 있다. iptables 는 데몬이 아닌 Netfilter 에 적용하는 규칙을 제공하는 명령어이다.
iptables <-t table> <option>
으로 구성된다.
테이블
Netfilter 에서 기본적으로 제공되는 테이블로 filter, nat, mangle, raw 가 있다. 테이블은 성격에 따라 정보(규칙과 체인)를 보관하는 장소(또는 기능의 집합)를 말한다. 즉 NAT 기능을 사용하고자 한다면 nat 를 사용해야 하며, filter 는 패킷차단과 같은 보안기능을 수행하고 나머지는 패킷들의 내용을 변경하는 기능을 의미한다. 그리고 앞의 명령어에서 별도 테이블 명을 부여하지 않는다면 디폴트로 '-t filter' 가 적용되게 된다.
옵션
테이블 내 들어가는 정보는 규칙을 엮은 체인으로 구성되어 있다. 규칙은 보안규칙이나 IP 수정 규칙등으로 구성된다. 그리고 옵션은 체인과 규격에 대한 입력과 수정 그리고 삭제 할 수 있는 기능을 제공한다. 그리고 패킷들은 iptables 에서 선언한 체인별로 입력된 순서에 따라 규칙을 적용받게 된다.
- -A(–append) : 규칙을 추가한다.
- -N(–new-chain) : 새로운 체인을 생성한다.
- -X(–delete-chain) : 체인을 제거한다.
- -P(–policy) : 체인 기본 정책이 무엇인지를 선언한다.
- -L(–list) : 체인의 규칙을 리스트한다.
- -F(–flush) : 체인 내의 모든 규칙을 제거하고 초기화 한다.
- -Z(–zero) : 체인 내의 모든 규칙의 패킷과 바이트의 카운트를 0으로 초기화한다.
- -D(–delete) : 규칙을 삭제한다. 특정 규칙에 대해서만 삭제하고자 한다면 '-D chain rulenum' 과 같이 규칙번호를 입력해야 한다.
- -R(–replace) : '-R chain rulenum' 과 같이 기존의 규칙을 새로운 규칙으로 대체한다.
- -I(–insert) : '-I chain rulenum' 과 같이 체인의 특정위치(규칙번호)에 규칙을 추가한다. 규칙을 추가하면 해당 위치에 있었던 규칙은 뒤로 밀리게 된다.
- -E(–rename-chain) : '-E old-chain new-chain' 체인의 이름을 변경한다.
기본적으로 제공하는 filter 테이블의 체인 종류는 다음과 같다.
- INPUT : 패킷(입력 패킷)을 수신하는 체인
- FORWARD : 수신된 패킷이 다시 외부로 전송되는 역할을 하는 체인(라우터에 방화벽을 적용할 때 쓰임)
- OUTPUT : 패킷(출력 패킷)을 외부로 전송하는 체인
앞의 filter 테이블에서 사용하는 3개의 기본 체인(INPUT, OUTPUT, FORWARD)은 수정이나 삭제할 수 없지만 사용자 정의에 따라 새로운 체인을 추가하여 위의 체인을 대신하여 사용할 수 있다. 사용자 정의 체인은 다음과 같은 방법으로 생성해 줄 수 있다.
'iptables -N <사용자 정의 체인 명>'
그리고 개별 체인에 대해 기본 정책을 설정할 수 있다. 만약 예와 같이 'iptables -P INPUT DROP' 으로 기본 정책을 준다면, 입력된 패킷이 규칙에 맞는 것이 없다면 기본정책으로 삭제(DROP)하라는 명령이다. 만약 기본 정책을 DROP 에서 ACCEPT 으로 바꾸어 주었을 경우, 규칙에 맞지 않는 모든 패킷은 허용하게 된다.
'iptables -P INPUT DROP'
'iptables -P OUTPUT DROP'
'iptables -P FORWARD DROP'
해당 규칙에 따라 매치되는 패킷들에 대한 처리는 '-j' 라는 옵션으로 처리된다.
- '-j DROP' 이라 설정하면 규칙에 맞는 패킷들은 삭제된다.
- '-j ACCEPT' 라 설정하면 규칙에 맞는 패킷들은 정상적으로 재전송(Forwarding)되거나 안드로이드로 수신(INPUT)또는 전송(OUTPUT)하게 된다.
- '-j MASQUERADE' 라 하면 패킷들은 NAT 규칙에 따라 소스 IP 를 전송되는 포트의 IP 주소로 바뀌어서 전송하라는 의미가 된다.
- '-j 사용자 정의 체인 명' 을 사용한다면, 패킷들은 사용자 정의 체인에 따라 규칙을 적용받으라는 의미가 된다.
기본 정책으로 규칙이 맞지 않는 입/출력 모든 패킷은 삭제하게 되고 허용하는 패킷은 웹과 관련된 포트 80 으로만 액세스를 허용한다면, 다음과 같은 규칙을 만들어 주면 된다.
'iptables -P INPUT DROP'
'iptables -P OUTPUT DROP'
'iptables -A INPUT -p tcp -m tcp –sport 80 -j ACCEPT'
'iptables -A OUTPUT -p tcp -m tcp –dport 80 -j ACCEPT'
위의 정책과 규칙을 적용한다면, 웹 브라우저에서 사용하는 TCP 포트 80만을 허용하므로 해당 안드로이드는 오직 웹사이트로의 접속만 가능해진다. 그 이외에 모든 통신 포트들은 차단됨을 의미한다. 그리고 만약 https 와 같은 보안 웹사이트로의 액세스를 허용하시려면 TCP 포트 443 도 역시 열어야 한다.
NAT 와 관련되어 기본적으로 제공하는 체인은 다음과 같은 종류가 있다.
- PREROUTING : REPROUTING 은 안드로이드 시스템이 커널에서 패킷 라우팅 작업하기 이전에 목적지 IP 에 대해 NAT 작업(변경)을 수행하라는 의미이다.
- POSTROUTING : POSTROUTING 은 커널에서 패킷 라우팅 작업이후 네트워크 포트를 통해 패킷을 전송하기 이전에 소스 IP 에 대해 NAT 작업을 수행하라는 의미이다.
앞에서 설명한 POSTROUTING 과 PREROUTING 기능은 서로 상대적이다. 위의 그림에서 보면 에드혹으로 연결된 노트북(IP 주소가 10.10.10.3)로부터 받는 요청패킷들은 안드로이드(게이트웨이 IP 주소는 10.10.10.1 이다)내에서 외부로 나갈 때, POSTROUTING 를 통해 패킷들의 소스 IP(노트북의 IP 주소는 10.10.10.3 이다)를 안드로이드의 무선 데이터 네트워크 디바이스의 IP 주소 210.134.62.124 로 변경하여 나가게 된다.
그리고 서버는 요청 패킷의 소스 IP 주소를 목적지 IP 주소(210.134.62.124)로 변경하여 응답 패킷들은 전송하게 된다. 안드로이드는 수신된 응답패킷을 노트북의 IP 주소로 PREROUTING 과정을 통해 목적지 IP 주소가 10.10.10.3 으로 복원되어 에드혹으로 연결된 노트북으로 다시 전달하게 된다.
테더링에서는 Netfilter 의 NAT 기능을 사용하고자 한다면 아래와 같이 설정하면 된다.
iptables -N wireless-tether ------------- 1 iptables -F wireless-tether ------------- 2 iptables -t nat -F PREROUTING ------------- 3 iptables -t nat -F POSTROUTING ------------- 4 iptables -t nat -F ------------- 5 iptables -A wireless-tether -m state --state ESTABLISHED,RELATED -j ACCEPT ------------- 6 iptables -A wireless-tether -s network -j ACCEPT ------------- 7 iptables -A wireless-tether -p 47 -j ACCEPT ------------- 8 iptables -A wireless-tether -j DROP ------------- 9 iptables -A FORWARD -j wireless-tether ------------- 10 iptables -t nat -I POSTROUTING -s network -j MASQUERADE ------------- 11
여기서 wireless-tether 는 개발자가 만든 체인이다. 패킷들이 Netfilter 에 의해 규칙을 적용받는 순서는 다음과 같다.
'PREROUTING → 라우팅 → FORWARDING → wireless-tether → POSTROUTING'
앞의 명령어는 먼저 주변기기에서 들어오는 패킷들은 PREROUTING 과 라우팅 과정 그리고 FORWARDING 을 거쳐 모두 wireless-tether 라는 체인을 타게 되면서 보안 규칙을 적용받게 된다. 그리고 마지막으로 POSTROUTING 를 통해 패킷의 소스 IP 는 송신되는 포트의 IP로 변경되어 전송하게 된다.
위 각각의 iptables 의 의미는 다음과 같다.
- 1~5번 : 앞서 설명한 iptables 의 내용이다.
- 6번 : 프로토콜 TCP 에 해당되는데, 3-Way Handshaking 으로 연결이 성립하면 커널 내에서는 클라이언트와 서버는 세션이 성립되었다고(또는 ESTABLISHED 되었다고)이야기 한다. RELATED 는 ESTABLISHED 된 패킷들로부터 파생된 패킷들(예를 들어 FTP 의 경우, 21번 포트 번호의 패킷들은 20번 포트번호의 패킷과 RELATED 관계가 성립한다)을 이야기한다. 이후에 성립된 패킷들은 정상적으로 처리하라는 의미이다. 3-Way Handshaking 은 TCP 가 처음 접속하기 위해 정상통신이 가능한지 양방향 체크하는 과정을 말한다.
- 7번 : network 로 수신되는 패킷들은 정상 처리하라는 의미로 여기서 -s 옵션은 소스 IP 를 뜻한다.
- 8번 : '-p 47' 은 프로토콜 47번을 의미한다. 프로토콜 47번 패킷들은 통신사에서 사용하는 GRE(General Routing Encapsulation) 패킷을 이야기하는데, 이 패킷들은 정상적으로 처리하라는 의미이다. 일반 3G 망에서는 공중망으로 뿌려지는 모든 패킷의 보안을 위해 GRE 라는 암호화된 패킷들을 사용한다.
- 9번 : 그 이외의 패킷들은 전부 삭제하라는 의미이다.
- 10번 : 포워딩되는 패킷들은 '-j wireless-tether' 라는 체인의 규칙을 적용받으라는 뜻이다.
- 11번 : 소스 IP 가 network 인 모든 패킷들(안드로이드가 애드혹으로 연결된 주변기기로부터 수신되는 패킷들)은 NAT 의 MASQUERADE 를 적용받아 3G 망으로 나가는 포트의 IP 주소로 바꾸어서 나가라는 뜻이 된다.
여기서 Network 는 DHCP 로 에드혹의 주변기기에서 제공한 사설 IP 범위를 의미한다.