2012년 8월 28일 화요일

리눅스를 이용하여 인터넷 공유하기

네트워크 어댑터가 2장 달린 컴퓨터라면 여러 가지의 일을 할 수 있다. 그 중 대표적인 것이 인터넷을 공유하는 것이다. 꽤 오래전 iptables가 나오기 전, ipchains를 이용하여 제한된 공식 IP 주소를 가지고 회사 내부의 컴퓨터를 외부 인터넷에 연결하도록 만든 적이 있었다. 기억이 정확하지는 않지만 아마도 알파 프로세서가 달린 컴퓨터를 이용했던 것 같다.

이제는 사양이 좀 뒤떨어지긴 했지만, 그래도 Xeon CPU가 달린 '서버' 보드를 쓰면서 내장되어 있는 네트워크 어댑터를 단 한장만 쓰고 있다니 이 어찌 부끄럽지 않은가! 기억을 더듬고 구글에 의존하면서 인터넷을 공유하는 방법을 알아보자.

우선 가장 간단한 환경에서 시작한다. 공식 IP 주소가 할당된 리눅스 컴퓨터가 있고(eth0), 여기에 네트워크 어댑터가 하나 더 있다고 가정하자(eth1). 그리고 인터넷 공유에 사용할 클라이언트 PC는 단 한대 뿐이라고 하자. 그러면 클라이언트 PC에 사설 IP를 부여한 뒤 이것과 리눅스 서버의 eth1을 크로스케이블로 연결한다. 그리고 리눅스 측에서 관리자 권한으로 다음과 같이 입력한다. 사실 여기서 보인 예제는 너무나 단순하다. 모름지기 방화벽이라면, 관리자의 입맛에 맞게 세부적인 설정을 할 줄 알아야 한다!


# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -P FORWARD DROP
# iptables -A FORWARD -o eth0 -j ACCEPT
# iptables -A FORWARD -o eth1 -j ACCEPT
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# ifconfig eth1 192.168.0.1 up

파랑색으로 표시한 첫번째와 마지막 줄에 대해서만 간단히 부연 설명을 하도록 하자. 정확히 말하자면 '인터넷 공유'는 리눅스의 현대적인 커널에 포함된 Netfilter subsystem이 담당하는 방화벽(firewall)기능 중의 일부에 지나지 않는다. 리눅스에서는 iptables가 이 기능을 하는데, 우분투에서는 이를 좀 더 편하게 설정하기 위해 ufw라는 유틸리티를 제공한다. 나는 iptables에 조금 더 친숙하므로, 이를 대상으로 설명하도록 하겠다.  첫번째 줄에 해당하는 것은 /etc/sysctl.conf 파일에서 다음 줄을 찾아 코멘트를 제거한 뒤 sudo sysctl -p 명령으로 설정을 적용하는 것으로 대신할 수 있다.

net.ipv4.ip_forward=1

마지막 줄은 일반적인 네트워크 카드 설정 메뉴에서 IP 주소를 부여하듯이 하면 된다. 아마 게이트웨이는 설정하지 않아도 될 것이다.

클라이언트 PC에서는

IP 주소: 192.168.0.2
서브넷 마스크: 255.255.255.0
게이트웨이: 192.168.0.1
DNS 서버: 환경에 맞는 것으로

이렇게만 해 두면 일단은 클라이언트 PC에서 인터넷을 사용할 수 있다. 하지만 여기에는 몇 가지 문제점이 따른다.

  1. 리눅스 서버를 껐다가 켜면 iptables 설정을 다시 해야 한다(변명: 실제로 서버측을 재부팅해 보았는데 여전히 클라이언트측에서는 인터넷 공유가 되고 있다. iptables 설정을 셧다운시에 자동으로 저장했다가 재부팅 시 다시 적용하도록 이미 셋업되어 있는 것으로 보인다)
  2. 클라이언트를 여러 대 쓰려면 사설 IP 주소를 어떻게 배정해야 할지 생각을 해야 한다(DHCP 서버 사용 - 수십대의 클라이언트 PC를 물릴 것이 아니므로, 그다지 절실하지는 않다).
그러면 각 상황별로 어떻게 하면 되는지 알아보도록 하자... 구글링을 하는 것도 좋지만, 우분투 support page의 공식 문서를 참조하는 것이 가장 확실한 방법이다. 나는 지금 우분투 서버 가이드(PDF file)를 읽고 있는 중이다.

iptables를 이용한 masquerading

'인터넷 공유(internet connection sharing)'라는 쉬운 표현을 썼지만, IP masquerading이 정확한 표현이다. IP masquerading은 외부에서 도달할 수 없는(non-routable) IP 주소를 갖는 사설 머신이 masqueraing을 제공하는 장비를 통해 외부 인터넷으로 접속하게 해 주는 것이라고 설명할 수 있다. 이를 가능하게 하려면, 내부에서 나오는 소스의 패킷을 변조(!)하여 마치 masquerading을 제공하는 장비로부터 나오는 것처럼 만들어야 하고, 다시 외부에서 들어오는 패킷에 대해 마찬가지의 수정을 가해서 이를 요청했던 사설 장비로 다시 되돌아가게 해야 한다.

기본 개념에 대해 설명하자면, 그 깊이는 이루 헤아리기 어렵다. "패킷"의 개념은 대충 이해하고 있다. 네크워크 상에서 전송될 내용물을 일정하게 자른 뒤, 최종 목적지(주소라고 해 두자)를 헤더에 적어 놓은 것을 패킷이라고 보면 된다. 그러면 체인은 무엇인가? 패킷들이 지나게 될 통로라고 하면 될까? 정책(ACCEPT, DENY, DROP)은 특정 체인을 지나가는 패킷에게 실제로 가해지는 동작으로서 이해하기는 쉽다. 체인에는 PREROUTING, INPUT, FORWARD, OUTPUT, 그리고 POSTROUTING의 다섯 가지가 있다. 위키피디아의 iptables 항목을 아무리 읽어 보아도 체인에 대한 설명은 잘 이해가 가지 않는다. 그러나 다행스러운 것은, 우분투 문서는 이론보다는 실전 예제 중심으로 되어 있다는 것. 위키피디아의 체인에 대한 설명 부분을 그냥 복사해 왔다. 두고 두고 반복하여 읽으면서 음미하도록 하자.


  • “PREROUTING”: Packets will enter this chain before a routing decision is made.
  • “INPUT”: Packet is going to be locally delivered. (N.B.: It does not have anything to do with processes having a socket open. Local delivery is controlled by the “local-delivery” routing table: `ip route show table local`.)
  • “FORWARD”: All packets that have been routed and were not for local delivery will traverse this chain.
  • “OUTPUT”: Packets sent from the machine itself will be visiting this chain.
  • “POSTROUTING”: Routing decision has been made. Packets enter this chain just before handing them off to the hardware.

윈도우 클라이언트가 접속할 내부 사설 IP를 192.168.0.0/24라고 가정하자. 그러면 다음과 같은 단일 iptables rule로 마스커레이딩이 가능하다. eth0은 외부로 향하는 네크워크 어댑터이다. 혹시 네트워크/호스트 ID의 표현 방법, 서브넷 나누는 방법 등의 사항이 궁금하면 Linux Network Configuration 페이지를 참조하자. 나도 아직 완벽하게 이해하고 있지 못하다^^

sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

재부팅시에도 이를 적용하려면 /etc/rc.local에 이 내용을 기록해 두면 된다. 단. /sbin/iptables라고 full path를 지정하지 않았더니 실행을 하지 못하는 띨띨함을 보였다! 또는 iptables-save와 iptables-restore 명령을 잘 쓰면 되겠다.

다음 내용은 아직 완벽하게 이해하지 못했다.

Also, each chain in the filter table (the default table, and where most or all packet filtering occurs) has a default policy of ACCEPT, but if you are creating a firewall in addition to a gateway device, you may have set the policies to DROP or REJECT, in which case your masqueraded traffic needs to be allowed through the FORWARD chain for the above rule to work:

sudo iptables -A FORWARD -s 192.168.0.0/16 -o ppp0 -j ACCEPT
sudo iptables -A FORWARD -d 192.168.0.0/16 -m state --state ESTABLISHED,RELATED -i ppp0 -j ACCEPT

The above commands will allow all connections from your local network to the Internet and all traffic related to those connections to return to the machine that initiated them.

* 참조한 사이트: 우분투 서버 가이드, http://www.yolinux.com/TUTORIALS/LinuxTutorialIptablesNetworkGateway.html

댓글 없음: