Linux Advanced Routing & Traffic Control HOWTO
Linux Advanced Routing & Traffic Control HOWTO
Bert Hubert
Netherlabs BV
bert.hubert(at)netherlabs.nl
Gregory Maxwell
greg(at)linuxpower.cx
Remco van Mook
remco(at)virtu.nl
Martijn van Oosterhout
kleptog(at)cupid.suninternet.com
Paul B Schroeder
paulsch(at)us.ibm.com
Jasper Spaans
jasper(at)spaans.ds9a.nl
Revision History
Revision $Revision: 1.52 $
![]()
1. 헌정 ¶이 문서는 많은 사람들의 열정이자 무언가 보답하고 싶은 나의 노력의 결과물이다. 적은 수나마 나타내면 아래와 같다.
2. 소개 ¶반갑습니다, 다정한 독자여.
이 문서는 리눅스 2.2/2.4를 가지고 어떻게 많은 것을 할 수 있는지 가르치기를 희망합니다. 많은 사용자들에게는 미지의 것이지만 멋진 일을 하게 해주는 도구들을 이미 실행해 봤을 겁니다. route 와 ifconfig 같은 명령은 사실 매우 강력한 iproute2 인프라를 둘러싼 얇은 껍질에 불과합니다.
나는 이 HOWTO가 Rusty Russell의 것 중 하나 netfilter와 같이 널리 읽히기를 바랍니다.
![]() 이 HOWTO에서 길을 잃기 전에 간단한 흐름 조절만 할 생각이면 모든걸 건너 뛰고 다른 가능성으로 가서 CBQ.init 을 읽으십시오.
2.1. 권리의 포기와 허가 ¶이 문서는 매우 유용하게 사용되리라 하는 희망하에 배포하지만, 아무런 보증도 하지 않습니다. 기계적이나 특정 목적에 맞는다는 암묵적인 보증도 없습니다.
짧게 얘기해서, STM-64 백본이 사용불능이 되거나 가장 중요한 고객에게 포르노가 전해진다고 해도 그건 우리의 잘못이 아닙니다. 미안합니다.
Copyright (c) 2002 by bert hubert, Gregory Maxwell, Martijn van Oosterhout, Remco van Mook, Paul B. Schroeder and others. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/).
이문서를 어떤 형식으로든 자유롭게 복사하고 배포(팔거나 혹은 주거나)하십시오. 수정과 논평은 문서 관리자에게 전달하도록 부탁합니다.
또한 이 문서를 출판한다면 저자에게 "검토" 목적으로 몇 개 보내주시길 부탁드립니다.
![]() 한글 번역의 저작권은 이재광과 기존 번역자 각각에게 있으며 Open Publication License v1.0 이나 이후 (최근 판은 http://www.opencontent.org/openpub/ 에 있습니다.)의 4절의 조건에 부합하는 경우에 재 배포될수 있습니다.
2.2. 사전 지식 ¶제목이 얘기 하는 것처럼 "고급" 하우투다. 로켓 과학을 얘기하는 건 아니지만 약간의 사전 지식이 있다고 가정한다.
여기 도움 줄 수 있는 몇개의 참고 문들을 소개한다.
![]() 네트웍이 무엇인가에 대해 매우 훌륭한 소개와 설명이 있고 어떻게 다른 네트웍과 연결되는지 얘기한다.
Linux Networking-HOWTO (전에는 Net-3 HOWTO)
2.3. 리눅스로 할 수 있는 것 들 ¶이런일을 할 수 있습니다 :
2.4. 문서에 대해 일러두기 ¶이 문서에 대해 미리 말해두고 싶은 것들이 몇 가지 있습니다. 문서의 대부분은 제가 작성했지만, 계속해서 같은 방법으로 문서를 유지해나가고 싶지는 않습니다. 저는 오픈소스에 대한 강력한 지지자로서 누구든지 이 문서에 대해 피드백을 보내주고, 갱신하거나 수정하는 것에 대해 환영입니다. 오탈자가 있거나 사소하게 잘못된 부분이 있더라도 언제든 제게 알려주십시오. 문체가 어딘지 딱딱하게 느껴진다면 필자가 영어민 아니라서 그러려니 생각해 주십시오. 제안할 내용을 보내는데 부담을 갖지 말아주십시오.
만약 당신이 어떤 섹션을 맡아서 유지하는데 스스로가 더 적당하다고 느끼신다면, 또는 새로운 섹션을 작성해서 유지해나가려고 한다면 그것 또한 환영합니다. 이 하우투의 SGML 판은 CVS 를 통해 구할 수 있습니다. 많은 분들이 이 문서를 협력해서 만들어나갈 수 있다면 정말 좋겠습니다.
덧붙여 이 문서를 읽다보면 많은 FIXME 표시를 보실겁니다. 수정은 언제나 대환영! FIXME 표시가 있는 부분을 읽으신다면 당신은 미지의 영역을 걷고 있는 것입니다. 표시가 붙어있지 않은 다른 부분에서는 오류가 전혀 없다는 의미는 물론 아닙니다만, 그만큼 더 조심해야 된다는 뜻이죠. 만약 어떤 내용에 대해 검증하셨다면 알려주십시오. 그러면 FIXME 표시를 삭제할 것입니다.
이 하우투에서는 몇가지 가정하고 있는 것이 있습니다. 이를테면 실제로는 좀 드물겠지만 인터넷 연결에 10 Mbit 이라든지 하는 내용입니다.
2.5. 접근, CVS와 수정본의 제출 ¶이 HOWTO 문서는 공식적으로
![]() 전 세계 어디서든 익명 CVS 엑세스가 가능합니다. 이는 여러가지 면에서 이점이 있는데, 이를통해 하우투의 새 버전을 얻거나 패치를 제출하는데 수고를 덜 수 있습니다.
게다가 문서를 유지하고 있는 저자들이 각각 작업할 수 있기 때문에 더욱 좋습니다.
$ export CVSROOT=:pserver:anon@outpost.ds9a.nl:/var/cvsroot $ cvs login CVS password: ['cvs'라고 치세요 ('는 빼시고)] $ cvs co 2.4routing cvs server: Updating 2.4routing U 2.4routing/2.4routing.sgml오류를 찾거나 추가하고자 하는 내용이 있는 경우는 직접 고치신 후 cvs diff -u 명령을 실행 한 결과를 우리에게 보내주십시오. postscript 와 dvi, pdf, html, plain text 등을 만들 수 있는 Makefile 도 제공하고 있습니다. 이러한 문서 포맷을 만들기 위해서는 docbook 과 docbook-utils, ghostscript, tetex 를 설치해 두어야 합니다.
2.6. 메일링 리스트 ¶저자들은 이 하우투에 대해 점점 더 많은 편지를 받게 되었는데, 메일링리스트를 개설하는 것이 모두에게 도움이 될 것이라는 것이 명백하다는 결정에 이르렀습니다.
![]() 메일링리스트를 통하지 않은 질문에 대해서는 저자들이 답하기를 매우 꺼려 할 것이란 것을 지적하고 넘어갑니다. 이는 메일링리스트가 일종의 지식의 주춧돌이 되길 원하기 때문입니다. 만약 질문이 있다면 우선 메일링 저장소를 검색해본 다음에 메일링리스트에 투고해주세요.
2.7. 문서의 구조 ¶우리는 시작부터 재미있는 내용들을 다루게 됩니다. 그래서 처음 이 문서를 읽을 때는 완전히 설명할 수 없는 부분도 있고, 완벽하지 않은 부분도 있습니다. 이런 부분에 대해서는 대충 넘어가십시오. 언젠가 나중에는 모든 것을 이해할 수 있을 겁니다.
라우팅과 필터링은 뚜렷하게 구별되는 두 분류인데, 필터링에 대해서는 Rusty 의 하우투에서 아주 잘 설명하고 있습니다. 여기서 읽어보세요 :
이 문서에서는 netfilter 와 iproute2 를 연동하여 할 수 있는 작업들을 중점적으로 다룹니다.
3.1. 왜 iproute2 인가 ? ¶현재 대부분 리눅스 배포본과 유닉스 시스템에서는 arp 나 ifconfig, route 와 같은 전통적인 명령어를 사용하고 있습니다. 이런 도구들이 동작하긴 하지만 커널 2.2 이후 리눅스에서는 의도하지 않은 동작을 보입니다. 예컨데 현재 GRE 터널은 라우팅을 구성하는 한 부분이지만 완벽히 다른 도구를 필요로 합니다.
iproute2와 함께라면 터널도 완전한 도구집합에 포함됩니다.
커널 2.2 이상 리눅스는 네트웍 하부 구조를 새로 설계 했습니다. 새로운 네트웍 코드는 리눅스가 일반 운영체제에 비교해 성능과 기능에 약간의 경쟁력을 갖도록 합니다. 사실 새로운 라우팅, 필터링, 분류 코드는 각각의 라우터, 방화벽, 흐름조절 제품이 제공하는 것보다 기능이 좋습니다.
새로운 네트워킹 개념은 사람들이 기존 운영체제의 뼈대를 토대로 그것들을 뒤섞어 만들어 냈습니다. 일관되게 계속한 작업은 네트워킹 코드를 별난 행동으로 채웠고, 마치 사람의 말과 비슷합니다. 과거에는 이런 일을 하는데 SunOS 처럼 따라했으나 이상적이진 않았습니다.
새로운 뼈대는 과거 리눅스가 닿지 못했던 기능을 명확히 표현할 수 있습니다.
3.2. iproute2 여행 ¶리눅스는 트래픽 제어 (Traffic Control)라 부르는 매우 정교한 대역폭 시스템을 가지고 있습니다. 이 시스템은 대역폭을 분류하고, 우선권을 제공하고, 공평하게 분배하고, 또는 들어오거나 나가는 트래픽을 제한 할 수 있는 여러가지 방법을 제공합니다.
이제 iproute2의 가능성으로 여행을 시작합니다.
3.3. 준비물 ¶우선 도구들을 설치했는지 확인합니다. RedHat 과 Debian 시스템에서 'iproute' 라는 패키지로 제공되고, 또는 ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss??????.tar.gz" 에서 구할 수 있습니다.
![]() 일부 iproute 의 기능들을 이용하기 위해서는 몇가지 커널 옵션들을 활성화(enable)해야만 합니다. 또한, RedHat 6.2 를 포함하여 그 이전 버전에서는 트래픽 제어에 필요한 대부분의 커널 기능이 기본 커널에서 빠져 있다는 점을 유의해야 합니다.
RedHat 7.2 는 기본 커널에 다 가지고 있습니다.
커널을 새로 컴파일하는 경우라면 netlink 기능을 포함해야 합니다. iproute2 가 필요로 하는 기능입니다.
3.4. 현재 설정 살펴보기 ¶놀라운 일일수도 있지만, iproute2 는 이미 설정이 되어 있습니다. ifconfig, route 와 같은 명령어는 이미 고급 시스템 호출을 사용하고 있지만, 대부분 기본 설정을 사용합니다.
ip 명렁어는 핵심적인 도구이며, 이를통해 인터페이스 정보를 살펴 보겠습니다.
3.4.1. ip로 연결(link) 상태 보기 ¶[ahu@home ahu]$ ip link list 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100 link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff 4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff 3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10 link/ppp 나타난 숫자들은 조금씩 다를 수 있겠지만, 아무튼 제가 집에서 쓰는 NAT 라우터의 설정은 위와 같습니다. 출력한 결과중에 직접 연관이 있는 것들만 설명합니다.
우선 loopback 인터페이스를 봅시다. 이것 없이 동작하는 컴퓨터도 있지만 일단 설명을 합니다. MTU (최대 전송 크기) 는 3924 옥텟(octet)이고, 큐에 들어가지 않도록 되어 있습니다. 그 이유는 loopback 인터페이스는 커널에서 가상으로 잡아놓은 것이기 때문입니다.
dummy 인터페이스는 지금은 건너 뜁니다. 이것은 당신 컴퓨터에는 없을 수도 있습니다. 다음으로 두 개의 물리적인 네트웍 인터페이스가 있습니다. 하나는 케이블 모뎀에 있고, 다른 하나는 집안의 이더넷망쪽에 있습니다. 게다가 ppp0 인터페이스도 있습니다.
IP 주소가 없다는 것을 유의하세요. iproute 는 '연결(link)' 과 'IP 주소' 를 분리합니다. IP aliasing 을 한다면 고유한 IP 주소는 어찌 보면 무의미해 집니다.
그렇지만 이더넷 인터페이스의 하드웨어 식별자가 되는 MAC 주소를 보여주고 있습니다.
3.4.2. ip 명령으로 IP 주소 보기 ¶[ahu@home ahu]$ ip address show 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 brd 127.255.255.255 scope host lo 2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100 link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff inet 10.0.0.1/8 brd 10.255.255.255 scope global eth0 4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff 3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10 link/ppp inet 212.64.94.251 peer 212.64.94.1/32 scope global ppp0 위의 출력 결과는 좀더 많은 정보를 보여줍니다. 어떤 카드가 어떤 주소를 가지고 있는지 모두 보여줍니다. 'inet'은 인터넷(IPv4)를 나타냅니다. 'inet' 말고도 다른 주소 가족(address family)들이 있지만 당장은 신경쓰지 마십시오.
남은 비트는 eth0 에 연결되므로, 예를 들면 10.0.0.1 과 마찬가지로 10.250.3.13 또한 eth0 에 직접 할당 할 수 있습니다.
ppp0 에서도 숫자만 다를 뿐 같은 원리입니다. ppp0 은 subnet mask 없이 212.64.94.251 의 주소를 갖고 있습니다. 이는 점대점(point-to-point) 연결을 의미하고, 따라서 212.64.94.251 이 아닌 모든 주소들은 원격지 라는 뜻이 됩니다. 그 외에도 다른 정보를 볼 수 있는데, 이 link 의 저편 끝에는 역시 하나의 주소 212.64.94.1 만이 존재함을 나타냅니다. /32 라는 것에서 '네트웍 비트' 가 없음을 알 려줍니다.
위에서 설명한 개념들을 이해하는 건 매우 중요합니다. 그렇지 않다면 이 하우투의 앞부분에서 소개했던 문서들을 참고하십시오.
혹시 위의 출력 결과 중에 'qdisc' 에 관심이 있을 수 있습니다. 이는 큐잉 규칙(Queueing Discipline)을 의미합니다. 나중에 매우 중요합니다.
3.4.3. ip 명령으로 라우팅 정보 보기 ¶이제 10.x.y.z 주소를 찾는법도 알았고, 212.64.94.1 까지 도달할 수 있습니다. 하지만 이것으로는 충분하지가 않습니다. 세상 모든 곳에 도달할 수 있는 방법이 필요합니다. 우리는 ppp(Point-to-Point Protocol) 연결을 통해 인터넷과 연결합니다. 212.64.94.1 은 우리의 패킷을 다른 곳으로 전달하고, 또한 그에대한 결과를 우리에게 되돌려줍니다.
[ahu@home ahu]$ ip route show 212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251 10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1 127.0.0.0/8 dev lo scope link default via 212.64.94.1 dev ppp0이 결과는 설명하지 않아도 쉽게 알 수 있을 것입니다. 처음 4 줄은 ip address show 라는 명령 그 자체가 의미하는 바를 명시적으로 보여주고 있습니다. 마지막 줄에서는 212.64.94.1 을 통해 바깥 세상으로 나갈 수 있다는 것을 나타냅니다. 이것은 기본 관문(gateway)입니다. 212.64.94.1 이 관문이라는 것은 via 라는 단어를 보고 알 수 있습니다. 패킷을 212.64.94.1 로 보내면 알아서 처리해 줍니다. 참고로 예전 route 명령의 결과는 이렇습니다 :
[ahu@home ahu]$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 212.64.94.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0 10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 0.0.0.0 212.64.94.1 0.0.0.0 UG 0 0 0 ppp0 3.5. ARP (Address Resolution Protocol) ¶ARP 는
![]() 아주 간단한 예를 살펴봅시다. 몇 대의 컴퓨터로 구성되는 네트웍이 하나 있다고 해 봅시다. 이 네트웍에는 IP 주소 10.0.0.1인 foo 와 10.0.0.2인 bar 가 있습니다. foo 는 bar 가 켜져있는지 확인하려고 ping 을 보내려고 합니다. 그런데 왠걸, foo 는 bar 가 어디에 있는지 모르고 있습니다. 그래서 foo 는 bar 에게 ping 을 보내기 전에 ARP 요청을 보내야 합니다. 이 ARP 요청은 마치 foo 가 전체 네트웍에 대해 "bar (10.0.0.2)! 어디있습니까?" 라고 외치는 것과 비슷합니다. ARP 요청으로 이 네트웍에 존재하는 모든 기기들은 foo 가 부르는 소리를 듣지만, 대답을 하는 것은 bar (10.0.0.2) 뿐입니다. bar 는 ARP 응답을 foo 에게 "foo (10.0.0.1), 난 여기 00:60:94:E9:08:12 에 있소."라고 직접 보냅니다. 이러한 간단한 메세지 전달로 네트웍상의 친구 bar 를 찾았다면, 이제 foo 는 bar가 어디에 있는지 잊기 전까지는 bar 와 통신할 수 있습니다. (통상 유닉스 시스템에서는 15분 동안 기억합니다.)
이제 어떻게 동작하는지 살펴봅시다. 현재의 arp/neighbor cache/table는 이렇습니다 :
[root@espa041 /home/src/iputils]# ip neigh show 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable위에서 보듯이 컴퓨터 espa041 (9.3.76.41) 은 espa042 (9.3.76.42) 와 espagate (9.3.76.1) 의 위치를 알고 있습니다. 이제 다른 컴퓨터를 arp 캐시에 추가합시다. [root@espa041 /home/paulsch/.gnome-desktop]# ping -c 1 espa043 PING espa043.austin.ibm.com (9.3.76.43) from 9.3.76.41 : 56(84) bytes of data. 64 bytes from 9.3.76.43: icmp_seq=0 ttl=255 time=0.9 ms --- espa043.austin.ibm.com ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.9/0.9/0.9 ms [root@espa041 /home/src/iputils]# ip neigh show 9.3.76.43 dev eth0 lladdr 00:06:29:21:80:20 nud reachable 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachableespa041 에서 espa043 으로 연결을 시도한 결과, espa043 의 하드웨어 주소/위치가 arp/neighbor 캐시에 추가되었습니다. 따라서 espa041 은 espa043 항목이 (둘사이에 아무런 통신이 없는 결과로 말미암아) 시간 초과가 생길 때까지 espa041인 경우 상대방 위치를 알고 있으므로 ARP 요청을 보낼 필요가 없습니다. 이번에는 espa043 을 arp 캐시에서 지워봅시다 :
[root@espa041 /home/src/iputils]# ip neigh delete 9.3.76.43 dev eth0 [root@espa041 /home/src/iputils]# ip neigh show 9.3.76.43 dev eth0 nud failed 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud staleespa041 은 다시 espa043 이 어디에 있는지 잃어버렸습니다. 다음에 espa043 과 통신하기 위해서는 ARP 요청을 다시 보내야만 합니다. 한편 espagate (9.3.76.1) 에 대해 "stale(진부한)" 상태로 바뀌었음을 알 수 있습니다. 이는 espagate 의 위치는 여전히 유효하지만, 그 컴퓨터로 연결할 때는 확인해 보아야 한다는 것을 의미합니다. 4. 규칙들 - 경로배정 정책 데이터베이스 (Routing Policy Database) ¶대형 라우터에는 많은 사람들이 연결되어 있고, 이 사람들은 각각 서로 다른 서비스 수준을 요구할 수 있습니다. 이 때 라우터 운영자는 이러한 문제를 해결할 수 있어야 합니다. 경로배정 정책 데이터 베이스를 이용하면 여러 종류의 경로 배정 표(routing table) 모음을 사용해서 이러한 작업이 가능하게 됩니다.
이 기능을 이용하기 위해서는 커널에 "IP: advanced router" 와 "IP: policy routing" 옵션을 포함해서 컴파일 해야 합니다.
커널이 패킷을 경로배정 할 때는 어떤 표를 사용 할지 먼저 고려합니다. 기본으로 세 개의 테이블이 있고, 전통적인 'route' 명령은 main 과 local 표를 수정 할 수 있습니다. ip 명령으로도 물론 가능합니다.
기본 규칙은 아래와 같습니다. :
[ahu@home ahu]$ ip rule list 0: from all lookup local 32766: from all lookup main 32767: from all lookup default위의 리스트는 모든 규칙의 우선순위를 보여줍니다. 여기 보이는 모든 규칙은 모든 패킷에 적용됩니다. ('from all') 'main' 표는 앞에서 ip route ls 의 결과에서 이미 본 적이 있습니다. 'local' 과 'default' 표는 처음 입니다. 재미있는 일을 하려면 다른 표를 가리키는 규칙을 만들면. 그 표를 통해 시스템 경로 배정 규칙을 뒤엎을 수 있습니다.
좀 더 잘 맞는 규칙이 있을 때 커널이 무엇을 하는지에 대한 정확한 의미는 Alexey 의 ip-cref 문서를 읽어보십시오.
4.1. 출처에 따른 단순한 경로 배정 정책 ¶실제 예제를 다시 봅시다. 리눅스 NAT('마스커레이딩') 라우터로 연결된 케이블 모뎀이 2개 있습니다. (실제로는 3개) 여기 사는 사람들은 인터넷 사용을 위해 제게 돈을 냅니다. 우리집에 사는 사람 중 한사람이 단순히 핫메일만 사용하고 돈을 적게 내길 원한다고 가정합시다. 이것은 제게도 좋은 일이고 결국 속도가 느린 케이블 모뎀을 사용할 것 입니다.
'빠른' 케이블모뎀은 212.64.94.251 이고 212.64.94.1 과 PPP 로 연결되어 있습니다. '느린' 케이블 모뎀은 여러가지 ip 를 받아올 수 있고, 예제에서는 212.64.78.148 이고, 195.96.98.253 으로 연결되어 있습니다.
local 표는 :
[ahu@home ahu]$ ip route list table local broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 local 10.0.0.1 dev eth0 proto kernel scope host src 10.0.0.1 broadcast 10.0.0.0 dev eth0 proto kernel scope link src 10.0.0.1 local 212.64.94.251 dev ppp0 proto kernel scope host src 212.64.94.251 broadcast 10.255.255.255 dev eth0 proto kernel scope link src 10.0.0.1 broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 local 212.64.78.148 dev ppp2 proto kernel scope host src 212.64.78.148 local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 많은 것들이 명확합니다만 이것들은 어디선가 반드시 설정해야만 하는 것들입니다. 하지만 이미 되어 있습니다. default 표는 비어 있습니다.
'main' 표를 봅시다:
[ahu@home ahu]$ ip route list table main 195.96.98.253 dev ppp2 proto kernel scope link src 212.64.78.148 212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251 10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1 127.0.0.0/8 dev lo scope link default via 212.64.94.1 dev ppp0우리가 'John' 이라고 부르는 가상의 동거인을 위한 새로운 규칙을 하나 만듭니다. 숫자로만 작업해야 하지만, /etc/iproute2/rt_tables 파일에 표를 추가하면 매우 쉽습니다. # echo 200 John >> /etc/iproute2/rt_tables # ip rule add from 10.0.0.10 table John # ip rule ls 0: from all lookup local 32765: from 10.0.0.10 lookup John 32766: from all lookup main 32767: from all lookup default이제 남은 일은 John 의 표를 만들고 경로 배정 캐시를 비우는(flush) 일입니다. # ip route add default via 195.96.98.253 dev ppp2 table John # ip route flush cache이제 다 되었습니다. 위에서 설명한 내용을 ip-up 스크립트에 추가하는 일은 여러분께 남겨드립니다. 4.2. 여러 상향 경로와 서비스 제공자를 위한 경로 배정 ¶흔히 보는 구성은 아래와 같습니다. 지역 네트웍 (혹은 단지 한개의 컴퓨터)을 인터넷에 연결해 주는 인터넷 연결 사업자가 두개 있습니다.
________ +------------+ / | | | +-------------+ 서비스 +------- __ | | 제공자 1 | / ___/ \_ +------+-------+ +------------+ | _/ \__ | if1 | / / \ | | | | 지역망 -----+ 리눅스라우터 | | 인터넷 \_ __/ | | | \__ __/ | if2 | \ \___/ +------+-------+ +------------+ | | | | \ +-------------+ 서비스 +------- | 제공자 2 | | +------------+ \________이런 설정은 두가지를 보통 사용합니다. 4.2.1. 분리 접근 ¶서비스 제공자 1 로 부르는 특정 서비스 제공자를 통해서 패킷이 온 경우를 첫째로 보자면 역시 같은 서비스 제공자를 통해 응답해야 합니다.
우선 몇개의 대체 이름을 지정합니다. $IF1 과 $IF2 를 각각 라우터의 첫번째, 두번째 인터페이스 (if1, if2) 의 이름이라고 합시다. $IP1 과 $IP2 는 각각 $IF1 과 $IF2 에 할당된 IP 주소라고 합니다. 그리고 $P1 과 $P2 는 각각 서비스 제공자 1 과 서비스 제공자 2 의 관문 IP 주소입니다. 마지막으로 $P1_NET 과 $P2_NET 은 각각 $P1 과 $P2 이 있는 IP 네트웍 입니다.
두 개의 경로 배정 표를 추가하고 그 이름을 각각 T1 과 T2 이라고 합니다. 이것은 /etc/iproute2/rt_tables 에 추가합니다. 이제 아래처럼 이 표에 대한 경로 배정을 할 수 있습니다 :
ip route add $P1_NET dev $IF1 src $IP1 table T1 ip route add default via $P1 table T1 ip route add $P2_NET dev $IF2 src $IP2 table T2 ip route add default via $P2 table T2별로 대단한 건 없습니다. 관문(gateway)으로 가는 경로를 하나 만들고 그 관문을 통해 기본 경로 배정을 합니다. 이것은 외부망으로 연결되는 인터넷 서비스 제공자가 하나인 경우와 같습니다. 다만 이 작업을 각 서비스 제공자 마다 별도의 표를 통해 경로를 설정한다는 것이 다릅니다. 위에서 처럼 관문을 포함하여 네트웍의 어떤 호스트라도 찾을 수 있는 방법을 알려주는 것만으로도 네트웍 경로 배정은 충분합니다. 다음으로 main 경로 배정표를 설정합니다. 인터페이스에 연결된 이웃에게 직접 경로 배정하면 됩니다. `src' 인수를 사용합니다. 이는 나가는 IP 주소를 지정했음을 나타냅니다.
ip route add $P1_NET dev $IF1 src $IP1 ip route add $P2_NET dev $IF2 src $IP2그리고 어떤 것을 기본 경로 우선할지 선택합니다 : ip route add default via $P1다음으로 경로 배정 규칙을 설정합니다. 이는 경로 배정을 할때 어떤 표를 사용할지 결정합니다. 이미 해당하는 출발지 주소를 설정해 두었으면 지정한 인터페이스를 통해 경로 배정 할 수 있습니다. ip rule add from $IP1 table T1 ip rule add from $IP2 table T2여기까지 특정한 인터페이스를 통해 들어오는 흐름에 대해 그 인터페이스를 사용해서 응답하도록 하는 명령어 모음입니다. 지금까지 매우 간단한 설정이었습니다. 이 설정은 지역 네트워크 혹은 마스커레이딩 상태라고 해도 라우터에서 동작하는 모든 프로세스에서는 잘 동작합니다. 만일 그렇지 않다면 두 서비스 제공자가 같이 제공하는 IP 영역이 있거나 두 서비스 제공자중 하나를 통해 마스커레이딩을 사용하려는 경우 일 것입니다. 앞서 두가지 경우에 모두 지역망에 있는 컴퓨터의 주소에 기반한 서비스 제공자 선택 경로 배정 규칙을 추가할 수 있습니다.
4.2.2. 부하 분산 ¶두번째 과제는 두 서비스 제공자를 통해 나가는 흐름의 양을 조절하는 방법입니다. 위에서 처럼 분리 접근을 해 놓았다면 어렵지 않습니다.
두 서비스 제공자중 하나를 기본 경로로 설정하는 대신, 기본 경로를 다중 경로로 지정합니다. 이렇게 하면 기본 커널에선 두 서비스 제공자를 통해 부하 분산을 합니다. 아래와 같이 하면 됩니다 (분리 접근에 있는 예제를 한번 더 합니다) :
ip route add default scope global nexthop via $P1 dev $IF1 weight 1 \ nexthop via $P2 dev $IF2 weight 1이렇게 하면 양쪽 서비스 제공자를 통해 부하 분산 경로 배정을 합니다. weight 인수를 사용하면 선호하는 서비스 제공자를 조율 할 수 있습니다. 부하 분산은 경로를 기반으로 하고있고, 이 경로들은 캐시되기 때문에 부하 분산은 불완전 하다는 것에 주의 하시오. 이것은 자주 방문하는 사이트는 항상 같은 서비스 제공자를 통해서만 연결 될 수도 있습니다.
나아가 이런 문제점을 해결하고 싶다면 Julian Anastasov 의 패치를
![]() 5. GRE 와 다른 터널들 ¶리눅스에는 세 가지 종류의 터널이 있습니다. IP in IP 터널링, GRE 터널링, 커널 외부의 터널 (예를 들어 PPTP 와 유사한 것) 이 그것입니다.
5.1. 터널에 대한 몇 가지 이야기 ¶터널을 사용하면 아주 특별하고 대단한 일을 해낼 수 있습니다. 반면 제대로 설정하지 않으면 모든 것을 완전히 망쳐놓을 수 있습니다. 그래서 무엇을 하는지 정확히 이해하지 못하는 분은 절대로 기본 경로를 터널 장치로 하도록 만들지 마십시오.
![]() 5.2. IP in IP 터널링 ¶이 터널링 방법은 리눅스에서는 오래전부터 지원하고 있습니다. 사용하기 위해서는 ipip.o 와 new_tunnel.o 의 두 커널 모듈이 필요합니다.
네트웍이 셋 있다고 해봅시다 : 내부 네트웍 A 와 B 가 있고, 그 사이에 네트웍 C 가 있습니다. (또는 인터넷이라고 합시다) 네트웍 A 는 :
network 10.0.1.0 netmask 255.255.255.0 router 10.0.1.1라우터의 주소는 네트웍 C 에서 172.16.17.18 입니다. 네트웍 B 는 :
network 10.0.2.0 netmask 255.255.255.0 router 10.0.2.1라우터의 주소는 네트웍 C 에서 172.19.20.21 입니다. 네트웍 C 에 대해서는 그저 네트웍 A 와 B 의 패킷들을 서로간에 전달해주는 것으로 생각합시다. 편리하게 인터넷을 사용한다고 생각해도 좋습니다.
여기 할일이 있습니다:
첫째, 모듈을 확실히 설치합니다:
insmod ipip.o insmod new_tunnel.o네트웍 A의 라우터에서 아래 처럼합니다: ifconfig tunl0 10.0.1.1 pointopoint 172.19.20.21 route add -net 10.0.2.0 netmask 255.255.255.0 dev tunl0네트웍 B의 라우터에선: ifconfig tunl0 10.0.2.1 pointopoint 172.16.17.18 route add -net 10.0.1.0 netmask 255.255.255.0 dev tunl0터널을 끝내려면: ifconfig tunl0 down빠르게 모든걸 마쳤습니다. IP-in-IP 터널을 통해서는 IPv6 나 방송을 보낼 수 없습니다. 이제 서로 통신하지 못했던 IPv4 네트웍을 두개 연결했고 그게 다 입니다. 호환성이 지켜지는 동안 이 명령들은 사용할 수 있습니다. 그것은 1.3 커널과 하위 호환을 갖는다는 것을 말합니다. 리눅스의 IP-in-IP 터널링은 다른 운영체제나 라우터와 같이 사용할 수 없습니다. 간단하고 잘 동작합니다. 반드시 써야 한다면 사용하십시오. 그렇지 않으면 GRE를 사용하십시오. 5.3. GRE 터널링 ¶GRE 는 원래 Cisco 에서 개발한 터널링 프로토콜인데 IP-in-IP 터널링에 비해 몇 가지 기능이 더 있습니다. 예를 들면 GRE 터널을 쓰면 멀티캐스트나 IPv6 을 처리할 수 있습니다.
리눅스는 ip_gre.o 모듈이 필요합니다.
5.3.1. IPv4 터널링 ¶우선 IPv4 터널링을 해봅시다:
우선 세개의 네트웍을 가지고 있다고 합시다: 내부 네트웍 A,B가 있고 그사이에 네트웍 C가 있습니다. (또는 인터넷)
네트웍 A는 :
network 10.0.1.0 netmask 255.255.255.0 router 10.0.1.1라우터는 네트웍 C에서 172.16.17.18을 주소로 가지고 있습니다. 이 네트웍을 neta라고 합시다. (물론 진짜는 아닙니다) 그리고 네트웍 B는 :
network 10.0.2.0 netmask 255.155.255.0 router 10.0.2.1라우터는 네트웍 C에서 172.19.20.21을 주소로 가지고 있습니다. 이 네트웍을 netb라고 합시다. (아직도 진짜는 아닙니다) 네트웍 C에 관해서는 A에서 B로가는 모든 패킷을 전달해 주는것으로 합시다. 어떻게 나 왜그래야 하나 하는것은 신경쓰지 맙시다.
네트웍 A에 있는 라우터에 다음과 같은일을 합시다:
ip tunnel add netb mode gre remote 172.19.20.21 local 127.16.17.18 ttl 255 ip link set netb up ip addr add 10.0.1.1 dev netb ip route add 10.0.2.0/24 dev netb이제 위의 일에 대해 조금 얘기해 봅시다. 첫번째줄, netb라는 터널 장치를 추가합니다(당연한일입니다 패킷을 보내려고 하는 곳이니까요). 게다가 GRE 프로토콜을 (mode gre)을 사용하고 원격지 주소가 172.19.20.21 (상대편 라우터 주소)이고 터널을 지나는 패킷이 172.16.17.18에서 출발한 것으로 하고 (이것은 라우터가 네트웍 C에서 여러개의 주소를 가지고 있을때 그 하나를 터널로 사용할수 있게 합니다) 패킷의 TTL을 255로 합니다(ttl 255). 두번째 줄은 장치를 활성화 시킵니다.
세번째 줄에서 새로운 netb에 주소를 10.0.1.1로 지정합니다. 작은 네트웍에선 이것으로 충분합니다만 땅굴파기를 시작한다면(많은 터널이 필요한경우)는 터널링 장치를 위해 다른 IP 대역을 사용하는것을 생각해 볼 수 있습니다(예를 들면 10.0.3.0을 사용할수 있습니다).
네번째 줄에서 네트워 B로가는 경로를 지정합니다. netmask에 사용한 표기법에 주의하십시오. 이 표기법에 익숙하지 않은분으 위해 설명을 드리면 netmask를 이진형태로 써 놓고 거기서 1의 개수를 세는 방법으로 사용합니다. 어떻게 그렇게 되는지 모르시는 분은 255.0.0.0은 /8, 255.255.0.0은 /16, 255.255.255.0은 /24를 기억하십시오. 혹시 궁금한 분을 위해서 255.255.254.0은 /23입니다.
이정도로 충분하고, 다음은 네트웍 B의 라우터로 가봅시다.
ip tunnel add neta mode gre remote 172.16.17.18 local 172.19.20.21 ttl 255 ip link set neta up ip addr add 10.0.2.1 dev neta ip route add 10.0.1.0/24 dev nta그리고 라우터 A에서 터널을 없애고 싶을때는: ip link set netb down ip tunnel del netb물론 라우터 B에서는 neta를 netb로 바꾸면 됩니다. 5.3.2. IPv6 터널링 ¶IPv6의 주소에 관해서는 6장을 보시오.
On with the tunnels.
아래와 같은 IPv6네트웍이 있고 6bone이나 친구에게 연결하려고 한다고 가정합시다.
Network 3ffe:406:5:1:5:a:2:1/96네트웍의 IPv4주소는 172.16.17.18이고 6bone 라우터의 IPv4주소는 172.22.23.24입니다. ip tunnel add sixbone mode sit remote 172.22.23.24 local 172.16.17.18 ttl 255 ip link set sixbone up ip addr add 3ffe:406:5:1:5:a:2:1/96 dev sixbone ip route add 3ffe::/15 dev sixbone위에 대해서 얘기해 봅시다. 첫번째줄, sixbone이라는 터널 장치를 만들었습니다. 모드를 sit(IPv4 터널링에 IPv6를 언는것)으로 하고 출발(local)과 도착(remote)을 지정했습니다. TTL은 최대값인 255로 지정합니다. 다음으로 장치를 활성화합니다 (up). 그후 네트웍 주소를 지정하고 터널을 통할 주소를 3ffe::/15(현재 모든 6bone의 주소)로 라우터에 지정합니다. GRE 터널은 현재 터널중에서 선호하는 터널입니다. 이것은 표준이고 리눅스 세계를 벗어나서도 넓게 사용하고 있으므로 좋은것입니다.
5.4. 사용자 영역 터널 ¶글 그대로 커널밖에는 터널을 구현한는 방법이 아주 많다. 가장 잘 알려진것은 PPP와 PPTP이고 그밖에도 아주 많이 (지적재산권이 있는것, 안전한것, 혹은 IP를 사용하지 않는것등)있고 그것들에 관해서는 이 하우투의 범위를 벗어난다.
6.1. IPv6 터널링 ¶이것은 리눅스의 터널링 능력에 대한 다른 응용입니다. 이것은 당신같은 IPv6의 탐험가나 얼리어댑터 사이에서 유명합니다. 아래의 '실습' 예제는 확실히 IPv6 터널링에 관한것만 하지 않습니다. 그러나, 이방법은 리눅스와 시스코의 IPv6 라우터사이의 터널에 자주 사용되며 경험상 많은 사람들이 후에 같은 일을 할 것입니다. 십분의 일로 당신에게도 적용됩니다.
![]() IPv6주소에 관해 조금:
IPv6주소는 IPv4 주소에 비해 진짜 큽니다: 128비트와 32비트. 그리고 우리가 원하는 것을 제공합니다:아주 아주 많은 IP주소들:정확히는 340,282,266,920,938,463,374,607,431,768,211,465. 이것을 떠나, IPv6(혹은 IPng, 다음세대의 IP)는 인터넷 중추 라우터에 좀더 작은 경로 배정표가 필요할것으로 예상되고 장비의 단순한 설정, IP 수준에서 좀더 안전하고 좀더 좋은 서비스 품질을 제공할 것입니다.
보기: 2002:836b:9820:0000:0000:0000:836b:9886
IPv6를 적는것은 큰 짐이 됩니다. 그래서 쉽게 하기 위한 몇가지 규칙이 있습니다:
IPv6는 IPv4의 후계자가 되려고 합니다. 왜냐하면 비교적 신기술이고 아직 세계적으로 본래의 IPv6 네트웍이 없기때문입니다. 전환을 빠르게 하려고 6bone이 소개되었습니다.
그것이 정확하게 터널에 발을 들여 놓는 것입니다.
IPv6를 사용하기 위해선 커널이 지원하도록 해야 합니다. 그것을 하기위한 만은 문서들이 있습니다. 그러나 그것은 모두 몇단계로 줄일수 있습니다:
요령: 'module' 옵션을 하지 않습니다. 종종 제대로 움직이지 않습니다.
다른말로 하면, IPv6를 커널에 내장해서 컴파일합니다. 설정을 보통처럼 저장하고 커널을 컴파일 합니다.
요령: 하기전에 Makefile을 고치는 것을 고려해 보십시오: EXTRAVERSION = -x; -->; EXTRAVERSION = -x-IPv6
커널을 컴파일하고 설치하는 많은 문서가 있지만 이 문서에서 얘기하고자 하는 것은 약간 다른 얘기입니다. 이 단계에 문제가 있다면 당신의 상세 조건에 맞추어 리눅스 커널을 컴파일하는 문서를 찾아 보십시오.
/usr/src/linux/README는 좋은 시작일 수 있습니다. 이것을 마친후에는 당신 상표의 새 커널로 부팅할 수 있고 '/sbin/ifconfig -a' 명령을 사용해 새 'sit0-device'를 볼 수 있습니다. SIT은 간단한 인터넷 변환 (Simple Internet Transition)을 나타냅니다. 이제 다음세대의 IP에 중요한 한걸음을 다가간 것을 자축할 수 있습니다.
![]() 다음 단계. 호스트 또는 전체 LAN을 다른 IPv6을 지원하는 네트웍에 연결하고자 할 수 있습니다. 이것이 "6bone"이 될것이고 이런 특별한 목적을 위해 설치합니다.
당신이 IPv6 네트웍: 3ffe:604:6:8::/64을 가지고 있고 친구나 6bone으로 연결하고자 한다고 가정합시다. /64 하위 네트웍 표현이 일반 IP 주소처럼 쓰인다는것에 주목해 주십시오.
# ip tunnel add sixbone mode sit remote 145.100.1.5 [local 145.100.24.181 ttl 255] # ip link set sixbone up # ip addr add 3FFE:604:6:7::2/126 dev sixbone # ip route add 3ffe::0/16 dev sixbone 위에 대해 이야기해 봅시다. 첫번째줄, sixbone으로 부르는 터널 장치를 만들었습니다. 터널의 모드를 sit (IPv4 터널에서 IPv6를 사용)으로 하고 출발 (local)에서 도착 (remote)할 곳을 지정했습니다. TTL은 최대값인 255로 지정했습니다.
다음, 장치를 활성시킵니다. 그 후, 우리 네트웍 주소를 추가하고 3ffe::/16 (현재 모든 6bone을 나타냄)으로 가능 경로틀 터널을 통하도록 했습니다. IPv6 관문 기계에서 실행하려면 다음 줄을 추가하는 것을 고려하십시오:
# echo 1 >/proc/sys/net/ipv6/conf/all/forwarding # /usr/local/sbin/radvd 나중에, radvd는 -zebra 처럼- IPv6 자동 설정 기능을 지원하는 라우터 광고 데몬입니다. 흥미 있다면 좋아하는 검색엔진을 통해 찾아 보십시오. 아래와 같이 검사할 수도 있습니다:
# /sbin/ip -f inet6 addr # /sbin/ip -f inet6 addr 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue inet6 ::1/128 scope host 3: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100 inet6 3ffe:604:6:8:5054:4cff:fe01:e3d6/64 scope global dynamic valid_lft forever preferred_lft 604646sec inet6 fe80::5054:4cff:fe01:e3d6/10 scope link bind를 IPv6 주소에 맞게 설정할 수 있습니다. A 형식은 IPv6에선 AAAA이다. in-addr.arpa는 ip6.int와 같다. 이 주제에 관해선 많은 정보가 있습니다.
IPv6를 지원하는 응용프로그램은 많이 늘어나고 있으며 그중에 secure shell, telnet, inetd, Mozilla, Apache와 그외 많은 다른것들이 포함됩니다. 그러나 이것들은 경로배정 문서에 관한 문서의 범위를 벗어납니다
![]() 시스코의 설정은 다음과 같이 됩니다:
! interface Tunnel1 description IPv6 tunnel no ip address no ip directed-broadcast ipv6 enable ipv6 address 3FFE:604:6:7::1/126 tunnel source Serial0 tunnel destination 145.100.24.181 tunnel mode ipv6ip ! ipv6 route 3FFE:604:6:8::/64 Tunnel1시스코가 당신 재산중에 없다면 인터넷에 있는 많은 IPv6 터널 중개인중 하나를 시도해 볼 수 있습니다. 그들은 시스코에 당신을 위한 추가 터널을 설정해 줄것 입니다. 대부분 쉬운 웹 인터페이스를 가지고 있습니다. 선호하는 검색엔진에 "ipv6 tunnel broker"로 찾아보십시오. 7. IPSEC: 인터넷 상의 안전한 IP ¶최근에 리눅스에서는 두 가지 종류의
![]() ![]() ![]() ![]() ![]() ![]() 더불어,
![]() ![]() ![]() ![]() ![]() ![]() ![]() 리눅스 2.5.47의 경우 커널 내에 자체적인 IPSEC 구현이 있습니다. 이는 Alexey Kuznetsov 및 Dave Miller가
![]() 이 HOWTO는 IPSEC의 2.5+ 버전만을 다룰 것입니다. 현재로선 리눅스 2.4 사용자에게 FreeS/WAN을 권하지만, 그 구성이 자체적인 IPSEC의 경우와는 다를 것이란 점을 염두에 두어야 합니다. 관련 소식에 따르면 현재 FreeS/WAN의 사용자공간 코드를 자체적인 리눅스 IPSEC과 함께 동작하도록 해 주는
![]() 2.5.49의 경우 IPSEC은 추가적인 패치 없이도 동작합니다.
주의 사용자 공간 도구들은
첫 번째로는, 두 호스트 간에 수동으로 보안 통신을 설정하는 법을 보일 것입니다. 이 과정의 상당 부분은 자동화 될 수도 있습니다만, 여기서는 '아랫 동네에서' 진행되는 일들에 익숙해 질 수 있도록 하기 위해 직접 해 보도록 하겠습니다.
![]() 커널을 컴파일 할 때 'PF_KEY'와 'AH', 'ESP', 그리고 CryptoAPI 안에 있는 모든 것들을 켜주는 걸 잊지 마세요!
경고 이 장의 저자는 제대로된 IPSEC 바부탱입니다! 없을 리가 없는 실수들을 찾게 되면 bert hubert<![]() 자동 키교환에만 관심이 있다면 다음 절을 건너뛰어도 무방합니다만, 수동 키입력(역자주: manual keying은 '수동 키입력'으로, automatic keying은 '자동 키교환'으로 번역합니다)을 어느 정도 이해하는 게 유용하다는 건 알고 계시길 바랍니다.
7.1. 수동 키입력 입문 ¶IPSEC은 복잡한 주제입니다. 많은 정보들이 온라인 상에 있으며, 이 HOWTO는 여러분들이 걸음마를 뗄 수 있도록 하는 것과 기본적인 원리들을 설명하는 것에 집중할 것입니다. 모든 예제들은 위에서 얘기한 링크에 있는 Rocoon에 기반하고 있습니다.
주의 많은 iptables 구성들은 IPSEC 패킷을 차단시킵니다! IPSEC을 통과시키려면: '
IPSEC은 InternetProtocol의 보안 버전을 제공해 줍니다. 이 맥락에서 보안이란 암호화(encryption)와 인증(authentication)이라는 상이한 두 가지를 뜻합니다. 보안에 대한 얕은 시각으로는 암호화만을 얘기할 수도 있겠지만, 그것만으로는 충분치 않다는 걸 쉽게 알 수 있습니다. 암호화를 해서 통신을 하고 있다고 해도, 원격지의 상대가 자신이 예상하고 있는 그 사람인지는 보장되지 않습니다.
iptables -A xxx -p 50 -j ACCEPT ' 및 'iptables -A xxx -p 51 -j ACCEPT '
IPSEC은 암호화를 위한 'Encapsulated Security Payload'(ESP)와 원격지의 상대를 인증하기 위한 'Authentication Header'(AH)를 지원합니다. 이 둘 모두를 설정할 수도 있고, 둘 중 하나만을 설정해 줄 수도 있습니다.
ESP와 AH 모두는 보안 연계(security association)에 의존하고 있습니다. 보안 연계(SA)는 출발지와 목적지, 그리고 지시사항으로 이루어져 있습니다. 간단한 인증 SA를 예로 들면 다음과 같습니다.
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-md5 "1234567890123456"; 이건 '10.0.0.11에서 10.0.0.216으로 가는 AH가 필요한 트래픽은 비밀값 1234567890123456을 쓰는 HMAC-MD5를 이용해서 서명할 수 있다'라는 얘기입니다. 이 지시는 SPI('Security Parameter Index') 아이디 '15700'이라는 딱지가 붙어 있는데, 이에 대해선 잠시 후 좀 더 설명하겠습니다. SA에 대한 흥미로운 점은 이게 대칭적이라는 겁니다. 통신의 양측이 정확히 동일한 SA를 공유하며, 상대편에서도 SA의 방향이 바뀌지 않습니다. 하지만 '자동 방향 바꿈' 규칙은 없다는 것에 유의해야 합니다. 이 SA는 10.0.0.11에서 10.0.0.216으로의 가능한 인증만을 기술하고 있습니다. 양방향 트래픽을 위해선 두 개의 SA가 필요합니다.
ESP SA의 예는 다음과 같습니다.
add 10.0.0.11 10.0.0.216 esp 15701 -E 3des-cbc "1234567890123456789012"; 이건 '10.0.0.11에서 10.0.0.216으로 가는 암호화가 필요한 트래픽은 키 1234567890123456789012를 쓰는 3des-cbc를 이용해서 암호화 할 수 있다'라는 얘기입니다. SPI 아이디는 '15701'입니다.
지금까지 살펴본 바로는, SA가 가능한 지시사항들을 서술하기는 하지만, 언제 이것들이 쓰여야 하는가 하는 정책은 사실 서술하지 않습니다. 실제로, SPI 아이디만 다른 거의 동일한 SA가 얼마든지 있을 수 있을 것입니다. 여기서 SPI는 보안 매개변수 색인(Security Parameter Index)을 뜻합니다. 실제 암호화를 하기 위해선 정책을 서술해 줄 필요가 있습니다. 이 정책에는 '가능한 경우 ipsec을 사용'이나 'ipsec이 없는 경우 트래픽을 차단' 같은 것들이 포함될 수 있습니다.
보통의 간단한 보안 정책(Security Policy; SP)은 다음과 같은 모습있니다.
spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require ah/transport//require; 호스트 10.0.0.216에서 입력된 경우라면, 이는 10.0.0.11을 향해 나가는 모든 트래픽을 암호화 하고서 AH 인증 헤더로 둘러싸야 한다는 걸 뜻합니다. 여기에 어떤 SA를 사용할지는 서술되어 있지 않다는 걸 알 수 있을 것입니다. 그걸 결정하는 건 커널의 할일입니다.
다시 말하자면, 보안 정책은 우리가 무엇을 원하는지를 지정하며, 보안 연계는 그걸 어떤 식으로 원하는지를 기술합니다.
나가는 패킷에는 커널이 암호화 및 인증에 사용한 SA SPI('어떤 식으로')가 꼬리표로 달려있어서, 이를 이용해 원격지에서 대응하는 검증 및 복호화 지시를 찾을 수 있습니다.
아래의 내용은 호스트 10.0.0.216에서 10.0.0.11로 암호화 및 인증을 이용해서 통신을 하는 아주 단순한 구성입니다. 이번 첫 번째 버전에서는 반대 방향이 평문으로 전달되기에 이 구성은 실제로 사용되어선 안 됨을 유의해 주십시오.
호스트 10.0.0.216에서는:
#!/sbin/setkey -f add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-md5 "1234567890123456"; add 10.0.0.216 10.0.0.11 esp 24501 -E 3des-cbc "1234567890123456789012"; spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require ah/transport//require; 호스트 10.0.0.11에서는, 동일한 보안 연계로, 보안 정책은 없이:
#!/sbin/setkey -f add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-md5 "1234567890123456"; add 10.0.0.216 10.0.0.11 esp 24501 -E 3des-cbc "1234567890123456789012"; 위 구성이 있으면 (이 파일들은 '
setkey '가 /sbin 에 설치되어 있으면 실행 가능합니다) 10.0.0.216에서 'ping 10.0.0.11 '을 하면 tcpdump에서 다음과 같이 보입니다.
23:37:52 10.0.0.216 > 10.0.0.11: AH(spi=0x00005fb4,seq=0xa): ESP(spi=0x00005fb5,seq=0xa) (DF) 22:37:52 10.0.0.11 > 10.0.0.216: icmp: echo reply 10.0.0.11에서 돌아오는 핑이 정말로 그냥 보인다는 걸 알 수 있습니다. 내보내는 핑은 당연히 tcpdump로 읽을 수 없지만, AH 및 ESP의 보안 매개변수 색인은 보여줍니다. 이 색인은 우리가 보낸 패킷의 신뢰성을 어떻게 검증하고 어떻게 이를 복호화 할 것인지를 10.0.0.11에게 알려 줍니다.
그런데 몇 가지를 좀 언급하겠습니다. 위의 구성은 여러 IPSEC 예제에서 보이는데, 아주 위험한 것입니다. 문제는 위의 구성이, 10.0.0.216이 10.0.0.11로 가는 패킷을 어떻게 처리해야 하는가에 대한 정책을 포함하고 있고 10.0.0.11이 그 패킷들을 어떻게 다뤄야 하는지는 설명하고 있지만, 10.0.0.11이 인증 혹은 암호화가 이뤄지지 않은 패킷을 버려야 한다고 알려주고 있지는 않다는 것입니다!
지금은 누구든 가짜 주소를 가진 전혀 암호화 안 된 데이터를 끼워넣을 수 있고, 10.0.0.11은 이를 그대로 받아들일 것입니다. 위 구성을 바로잡으려면 다음과 같이, 10.0.0.11 상에 들어오는 방향의 보안 정책이 필요합니다.
#!/sbin/setkey -f spdadd 10.0.0.216 10.0.0.11 any -P IN ipsec esp/transport//require ah/transport//require; 이 정책은 10.0.0.216에서 오는 모든 패킷은 유효한 ESP 및 AH여야 함을 10.0.0.11에게 알려 주고 있습니다.
이제, 이 구성을 완성하기 위해선 돌아오는 트래픽도 당연히 암호화 및 인증이 되도록 해야 합니다. 10.0.0.216에서의 완전한 구성은:
#!/sbin/setkey -f flush; spdflush; # AH add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-md5 "1234567890123456"; add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-md5 "1234567890123456"; # ESP add 10.0.0.11 10.0.0.216 esp 15701 -E 3des-cbc "123456789012123456789012"; add 10.0.0.216 10.0.0.11 esp 24501 -E 3des-cbc "123456789012123456789012"; spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require ah/transport//require; spdadd 10.0.0.11 10.0.0.216 any -P in ipsec esp/transport//require ah/transport//require; 그리고 10.0.0.11에서는:
#!/sbin/setkey -f flush; spdflush; # AH add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-md5 "1234567890123456"; add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-md5 "1234567890123456"; # ESP add 10.0.0.11 10.0.0.216 esp 15701 -E 3des-cbc "123456789012123456789012"; add 10.0.0.216 10.0.0.11 esp 24501 -E 3des-cbc "123456789012123456789012"; spdadd 10.0.0.11 10.0.0.216 any -P out ipsec esp/transport//require ah/transport//require; spdadd 10.0.0.216 10.0.0.11 any -P in ipsec esp/transport//require ah/transport//require; 이 예제에서 트래픽의 양방향 모두에 동일한 키를 사용했음을 알 수 있습니다. 하지만 이건 전혀 필수적인 것이 아닙니다.
방금 만든 구성을 확인해 보려면,
setkey -D 를 실행해서 보안 연계를 보거나 setkey -DP 를 실행해서 구성된 정책을 보면 됩니다.
7.2. 자동 키교환 ¶이전 절에서는 단순한 공유 비밀값을 이용해서 암호화가 구성되었습니다. 달리 말하자면, 안전한 상태가 유지되기 위해선 우리의 암호화 구성을 신뢰할 수 있는 경로를 통해 전달해 줄 필요가 있습니다. 우리가 텔넷을 통해 원격 호스트를 구성해야 한다고 하면, 어느 제삼자가 우리의 공유 비밀값을 알게 되고 설정은 안전하지가 않게 될 것입니다.
더불어, 비밀값이 공유되고 있기에 이는 비밀이 아닙니다. 원격측에서 우리의 비밀값으로 여러 가지를 할 수는 없지만, 그래도 우린 모든 상대와의 통신에서 서로 다른 비밀값을 사용하도록 해줄 필요가 있습니다. 이는 많은 수의 키를 필요로 합니다. 10명이 통신을 하려면 최소한 50개의 서로 다른 비밀값이 필요합니다.
대칭키 문제 말고도, 키 회전(rollover)이 필요하기도 합니다. 제삼자가 이럭저럭 충분한 양의 트래픽을 훔쳐보고 나면 키를 역공학으로 알아낼 수 있는 상태가 될 수도 있습니다. 일정 시간마다 새로운 키로 옮겨감으로써 이를 방지할 수 있지만, 이 과정은 자동화 될 필요가 있습니다.
또다른 문제는, 위에서 설명한 수동 키입력의 경우 사용되는 알고리즘 및 키 길이 같은, 원격측과의 많은 조정을 필요로 하는 것들을 우리가 정확하게 지정한다는 것입니다. '최소 다음과 같은 키 길이를 가진 3DES 및 Blowfish를 사용할 수 있다' 같은 좀더 일반적인 키 정책을 기술할 수 있게 되는 것이 바람직합니다.
이 문제들을 해결하기 위해 IPSEC은 Internet Key Exchange 프로토콜을 제공하여 난수적으로 생성된 키를 자동으로 교환하며, 이 키는 협상된 알고리즘 세부 사항에 따라서 비대칭 암호화 기술을 이용해 전송됩니다.
리눅스 2.5의 IPSEC 구현은
![]() ![]() #include <net/route.h> 를 제거해 줘야 할 수도 있기는 하지만, 컴파일이 가능합니다. 대신 제가 제공하는 ![]() 노트 IKE는 UDP 포트 500에 대한 접근을 필요로 하니, iptables가 이 포트를 막지 않도록 해 주세요.
7.2.1. 이론 ¶앞서 설명한 것처럼, 자동 키교환은 우리를 대신해 많은 일들을 해 줍니다. 구체적으로 말하자면, 바쁘게 보안 연계를 만들어 줍니다. 하지만, 당연히 그래야 겠지만, 우리 대신 정책을 설정하지는 않습니다.
고로 IKE의 덕을 보자면, 정책은 설정하되 어떤 SA도 제공해 주지 말아야 합니다. IPSEC 정책은 있는데 보안 연계는 없다는 걸 커널이 발견하면 이를 IKE 데몬에게 알려주고, 그럼 데몬은 보안 연계를 협상하려고 시도하는 작업에 착수합니다.
다시 말하는데, 보안 정책은 우리가 무엇을 원하는지를 지정하며, 보안 연계는 우리가 이를 어떤 식으로 원하는지를 기술합니다. 자동 키교환을 사용함으로써 우리는 무엇을 원하는가를 지정하는 것만으로도 충분하게 됩니다.
7.2.2. 예제 ¶Kame racoon에는 굉장히 많은 옵션들이 제공되는데, 대부분의 옵션들은 아주 훌륭한 기본값을 가지고 있어서 우리가 건드려 주지 않아도 됩니다. 위에서 설명한 것처럼, 운용자는 보안 정책을 정의해야 하며, 보안 연계는 정의할 필요가 없습니다. 그걸 협상하는 건 IKE 데몬에게 남겨 주는 것이지요.
이 예제에서는 10.0.0.11과 10.0.0.216이 또다시 안전한 통신을 설정하려고 하고 있으며, 이번에는 racoon의 도움을 받게 됩니다. 단순함을 위해 이 구성에서는 무시무시한 '공유 비밀값'인 사전 공유키(pre-shared key; PSK)를 사용하게 됩니다. X.509 인증서는 별도의 절에서 논의되니, 7.2.3절을 참고해 주십시오.
우리는 양쪽 호스트 모두에서 동일하게, 기본 구성을 거의 그대로 사용하려고 합니다.
path pre_shared_key "/usr/local/etc/racoon/psk.txt"; remote anonymous { exchange_mode aggressive,main; doi ipsec_doi; situation identity_only; my_identifier address; lifetime time 2 min; # sec,min,hour initial_contact on; proposal_check obey; # obey, strict or claim proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method pre_shared_key; dh_group 2; } } sainfo anonymous { pfs_group 1; lifetime time 2 min; encryption_algorithm 3des ; authentication_algorithm hmac_sha1; compression_algorithm deflate; }상당한 양의 설정입니다. 제 생각에는 아직 더 많은 내용들을 제거해서 기본 구성에 가깝게 만들 수 있을 것 같습니다. 주목할 것이 있습니다. 우리는 어떤 원격 상대에 대해서도 사용할 수 있는 두 개의 익명 설정을 구성함으로써, 이후의 구성을 수월하게 할 것입니다. 정말로 원하는 게 아니라면 여기에 호스트별 구절들이 필요하지는 않습니다. 더불어, 우리는 IP 주소에 기반해서 자신을 나타내도록 설정했으며('
my_identifier address '), 3des와 sha1을 쓸 수 있으며 psk.txt에 있는 사전 공유키를 사용할 것이라고 선언하고 있습니다.
psk.txt의 경우는, 양쪽 호스트에서 서로 다르게 두 가지 내용을 설정해 줍니다. 10.0.0.11에서는:
10.0.0.216 password2 그리고 10.0.0.216에서는:
10.0.0.11 password2 이 파일의 소유자는 root이고 모드는 0600으로 설정돼 있어야 합니다. 안 그러면 racoon은 그 내용을 신뢰하지 않을 겁니다. 이 파일들이 서로에게 거울상이라는 점에 유의해 주십시오.
이제 충분히 단순한 것이긴 하지만, 우리가 원하는 정책을 설정할 준비가 되었습니다. 호스트 10.0.0.216에서는:
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.216 10.0.0.11 any -P out ipsec esp/transport//require; spdadd 10.0.0.11 10.0.0.216 any -P in ipsec esp/transport//require; 그리고 10.0.0.11에서는:
#!/sbin/setkey -f flush; spdflush; spdadd 10.0.0.11 10.0.0.216 any -P out ipsec esp/transport//require; spdadd 10.0.0.216 10.0.0.11 any -P in ipsec esp/transport//require; 이 정책들이 마찬가지로 서로 대칭을 이루고 있다는 데에 유의해 주십시오.
드디어 racoon의 출발 준비가 완료됐습니다! 일단 시작되고 나면, 우리가 10.0.0.11에서 10.0.0.216으로 텔넷이나 그 비슷한 걸 하려고 하는 순간 racoon이 협상을 시작하게 됩니다.
12:18:44: INFO: isakmp.c:1689:isakmp_post_acquire(): IPsec-SA request for 10.0.0.11 queued due to no phase1 found. 12:18:44: INFO: isakmp.c:794:isakmp_ph1begin_i(): initiate new phase 1 negotiation: 10.0.0.216[500]<=>10.0.0.11[500] 12:18:44: INFO: isakmp.c:799:isakmp_ph1begin_i(): begin Aggressive mode. 12:18:44: INFO: vendorid.c:128:check_vendorid(): received Vendor ID: KAME/racoon 12:18:44: NOTIFY: oakley.c:2037:oakley_skeyid(): couldn't find the proper pskey, try to get one by the peer's address. 12:18:44: INFO: isakmp.c:2417:log_ph1established(): ISAKMP-SA established 10.0.0.216[500]-10.0.0.11[500] spi:044d25dede78a4d1:ff01e5b4804f0680 12:18:45: INFO: isakmp.c:938:isakmp_ph2begin_i(): initiate new phase 2 negotiation: 10.0.0.216[0]<=>10.0.0.11[0] 12:18:45: INFO: pfkey.c:1106:pk_recvupdate(): IPsec-SA established: ESP/Transport 10.0.0.11->10.0.0.216 spi=44556347(0x2a7e03b) 12:18:45: INFO: pfkey.c:1318:pk_recvadd(): IPsec-SA established: ESP/Transport 10.0.0.216->10.0.0.11 spi=15863890(0xf21052) 보안 연계를 보여주는
setkey -D 를 지금 실행해 보면, 실제로 확인을 할 수 있습니다.
10.0.0.216 10.0.0.11 esp mode=transport spi=224162611(0x0d5c7333) reqid=0(0x00000000) E: 3des-cbc 5d421c1b d33b2a9f 4e9055e3 857db9fc 211d9c95 ebaead04 A: hmac-sha1 c5537d66 f3c5d869 bd736ae2 08d22133 27f7aa99 seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: Nov 11 12:29:12 2002 hard: 0(s) soft: 0(s) current: 304(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 3 hard: 0 soft: 0 sadb_seq=1 pid=17112 refcnt=0 10.0.0.11 10.0.0.216 esp mode=transport spi=165123736(0x09d79698) reqid=0(0x00000000) E: 3des-cbc d7af8466 acd4f14c 872c5443 ec45a719 d4b3fde1 8d239d6a A: hmac-sha1 41ccc388 4568ac49 19e4e024 628e240c 141ffe2f seq=0x00000000 replay=4 flags=0x00000000 state=mature created: Nov 11 12:28:45 2002 current: Nov 11 12:29:16 2002 diff: 31(s) hard: 600(s) soft: 480(s) last: hard: 0(s) soft: 0(s) current: 231(bytes) hard: 0(bytes) soft: 0(bytes) allocated: 2 hard: 0 soft: 0 sadb_seq=0 pid=17112 refcnt=0 직접 구성해 준 보안 정책도 확인할 수 있습니다.
10.0.0.11[any] 10.0.0.216[any] tcp in ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:29:12 2002 lifetime:0(s) validtime:0(s) spid=3616 seq=5 pid=17134 refcnt=3 10.0.0.216[any] 10.0.0.11[any] tcp out ipsec esp/transport//require created:Nov 11 12:28:28 2002 lastused:Nov 11 12:28:44 2002 lifetime:0(s) validtime:0(s) spid=3609 seq=4 pid=17134 refcnt=3 7.2.2.1. 문제점 및 알려진 결함 ¶동작을 하지 않는다면 모든 설정 파일들의 소유자가 root이며, root만 읽을 수 있도록 되어 있는지를 확인해 보십시오. racoon을 foreground로 실행하려면 '
-F '를 쓰면 됩니다. 컴파일 된 위치에 있는 것 대신 특정 설정 파일을 읽도록 강제하려면 '-f '를 쓰십시오. 무지막지한 양의 세부 내용들을 보려면 racoon.conf에 'log debug; '를 추가해 주십시오.
7.2.3. X.509 인증서를 이용한 자동 키교환 ¶앞서 언급한 것처럼, 공유 비밀값의 사용은 쉽지가 않은데, 쉽게 공유될 수가 없는 데다가 일단 공유되고 나면 더이상 비밀이 아니게 되기 때문입니다. 다행히도 비대칭 암호화 기술이 있어서 이 문제의 해결을 도와줄 수 있습니다.
각 IPSEC 참여자 각각이 공개키(public key)와 개인키(private key)를 만들면, 양쪽 모두가 자신의 공개키를 공포하고 정책을 설정함으로써 안전한 통신을 조직할 수 있습니다.
얼마간의 작업이 필요하기는 하지만, 키를 만드는 건 꽤 쉽습니다. 다음 내용은 '
openssl ' 도구를 바탕으로 하고 있습니다.
7.2.3.1. 호스트를 위한 X.509 인증서 만들기 ¶![]() 먼저 우리는 'laptop'이라고 이름붙인 우리 호스트를 위한 '인증서 요청'을 발행합니다:
$ openssl req -new -nodes -newkey rsa:1024 -sha1 -keyform PEM -keyout \ laptop.private -outform PEM -out request.pem 그러면 몇 가지 질문을 받게 됩니다:
Country Name (2 letter code) [AU]:NL State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:Delft Organization Name (eg, company) [Internet Widgits Pty Ltd]:Linux Advanced Routing & Traffic Control Organizational Unit Name (eg, section) []:laptop Common Name (eg, YOUR name) []:bert hubert Email Address []:ahu@ds9a.nl Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: 이걸 얼마나 완전하게 채워넣을 것인가는 각자의 결정에 맡기도록 하겠습니다. 보안 요구에 따라서, 호스트 이름을 넣을 수도 있고 그러지 않을 수도 있습니다. 이 예에서는 넣었습니다.
이제는 이 요청을 '자가 서명'하도록 하겠습니다:
$ openssl x509 -req -in request.pem -signkey laptop.private -out \ laptop.public Signature ok subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic \ Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl Getting Private key 이제 'request.pem' 파일은 버려도 됩니다.
이 과정을 키가 필요한 모든 호스트에 대해 반복해 주십시오. '.public' 파일은 아무 문제 없이 배포할 수 있지만, '.private' 파일은 개인적으로 유지해야 합니다!
7.2.3.2. 설정 및 시동 ¶우리 호스트들을 위한 공개키 및 개인키가 준비되고 나면, racoon에게 이를 사용하라고 얘기해 줄 수 있습니다.
이전의 구성과 10.0.0.11 ('upstairs') 및 10.0.0.216 ('laptop') 두 호스트의 경우로 돌아가도록 하겠습니다.
10.0.0.11에서
racoon.conf 파일에 다음을 추가합니다:
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.216 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "upstairs.public" "upstairs.private"; peers_certfile "laptop.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2; } } 이 구성은 인증서를
/usr/local/etc/racoon/certs/ 에서 찾을 수 있다고 racoon에게 알려주고 있습니다. 더불어, 원격 호스트 10.0.0.216에 고유한 설정 항목들을 포함하고 있습니다.
'
asn1dn '이 들어 있는 줄은 로컬 및 원격 종단 모두의 식별자를 공개키에서 추출해야 한다고 얘기해 주고 있습니다. 이건 위에 나왔던 'subject=/C=NL/L=Delft/O=Linux Advanced Routing & Traffic Control/OU=laptop/CN=bert hubert/Email=ahu@ds9a.nl ' 출력 부분입니다.
certificate_type 행은 로컬의 공개키 및 개인키를 설정합니다. peers_certfile 문장은 racoon이 원격 호스트의 공개키를 파일 laptop.public 에서 읽어 오도록 설정합니다.
proposal 블럭은 authentication_method 가 rsasig 인 걸 제외하고는 앞서 본 것과 다르지 않습니다. 그 줄은 인증을 위해 RSA 공개/개인키를 사용할 것을 지시하고 있습니다.
10.0.0.216의 구성에 대한 추가 내용은 일반적인 자리바꿈을 제외하고는 거의 동일합니다:
path certificate "/usr/local/etc/racoon/certs"; remote 10.0.0.11 { exchange_mode aggressive,main; my_identifier asn1dn; peers_identifier asn1dn; certificate_type x509 "laptop.public" "laptop.private"; peers_certfile "upstairs.public"; proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; dh_group 2; } } 이제 이 문장들을 두 호스트 모두에게 추가해 주었으니, 키 파일을 제자리에 가져다 두기만 하면 됩니다. 'upstairs' 장비는
/usr/local/etc/racoon/certs 안에 upstairs.private , upstairs.public , 그리고 laptop.public 파일이 있어야 합니다. 이 디렉터리의 소유자가 root이며 모드가 0700임을 확인하십시오. 그렇지 않으면 racoon은 파일을 읽기를 거부할 수도 있습니다!
'laptop' 장비는
/usr/local/etc/racoon/certs 안에 laptop.private , laptop.public , 그리고 upstairs.public 을 필요로 합니다. 달리 말하자면, 각 호스트는 자신의 공개키 및 비밀키, 거기에 더해서 원격 호스트의 공개키를 필요로 합니다.
보안 정책이 제자리에 있는지 확인하십시오 (7.2.2절에 '
spdadd ' 행들을 실행하십시오). 그리고 racoon을 시동하면 모든 게 동작할 겁니다.
7.2.3.3. 안전하게 터널을 구성하는 방법 ¶원격측과의 안전한 통신을 구성하기 위해선 공개키를 교환해야 합니다. 공개키는 비밀로 유지해야 할 필요가 없는 반면, 대신 키가 실제로 변경되지 않은 키라는 걸 보장하는 게 매우 중요합니다. 달리 말하자면, '사이에서 뭔가를 하는 자(man in the middle)'가 없다는 게 확실해야 합니다.
이를 돕기 위해 OpenSSL은 '
digest ' 명령을 제공합니다:
$ openssl dgst upstairs.public MD5(upstairs.public)= 78a3bddafb4d681c1ca8ed4d23da4ff1 이제 우리가 해야 할 일이란 원격지의 상대가 동일한 다이제스트를 보는지 확인하는 것입니다. 이는 실제 삶에서 만나는 식으로도 가능하겠고, 전화를 통해서도 가능한데, 이때는 원격 상대의 전화 번호가 키를 담고 있던 이메일에서 함께 보내지지는 않았는지 확인해야 합니다!
이를 위한 또다른 방법은 인증 기관을 운영하는 신뢰하는 제삼자(
![]() 7.3. IPSEC 터널 ¶지금까지 우리는 소위 말하는 '트랜스포트(transport)' 모드에서의 IPSEC만을 살펴보았습니다. 이 모드에선 양쪽 종점 모두가 IPSEC을 직접 수행합니다. 이런 경우가 흔치는 않기에, 라우터만 IPSEC에 대해서 알고 있도록 하고 다른 호스트들을 대신해서 필요한 작업들을 하도록 해야 할 수도 있습니다. 이런 걸 '터널(tunnel) 모드'라고 합니다.
이 모드를 설정하는 건 식은 죽 먹기입니다. 10.0.0.216에서 10.0.0.11을 거쳐서 130.161.0.0/16으로 가는 모든 트래픽을 터널을 통하도록 하기 위해선, 10.0.0.216에서 다음과 같은 명령을 작성해 주면 됩니다:
#!/sbin/setkey -f flush; spdflush; add 10.0.0.216 10.0.0.11 esp 34501 -m tunnel -E 3des-cbc "123456789012123456789012"; spdadd 10.0.0.0/24 130.161.0.0/16 any -P out ipsec esp/tunnel/10.0.0.216-10.0.0.11/require;' -m tunnel '이 보이는데, 이게 굉장히 중요한 겁니다! 이 설정은 먼저 두 터널 종점인 10.0.0.216과 10.0.0.11 사이에서 ESP 암호화 SA를 구성합니다.
다음에는 실제 터널이 구성됩니다. 10.0.0.0/24에서 130.161.0.0/16으로 라우팅 해야 하는 모든 트래픽을 암호화 하도록 커널에게 지시합니다. 그리고 암호화된 이 트래픽은 10.0.0.11로 보내지게 됩니다.
10.0.0.11에서도 뭔가 설정이 필요합니다:
#!/sbin/setkey -f flush; spdflush; add 10.0.0.216 10.0.0.11 esp 34501 -m tunnel -E 3des-cbc "123456789012123456789012"; spdadd 10.0.0.0/24 130.161.0.0/16 any -P in ipsec esp/tunnel/10.0.0.216-10.0.0.11/require;이 설정은 ' -P out '이 '-P in '으로 바뀐 걸 빼고는 앞의 설정과 동일함을 알 수 있습니다. 앞서의 예제와 마찬가지로, 우리는 지금 한 방향으로 가는 트래픽만을 구성한 것입니다. 터널의 다른 절반을 완성하는 건 독자의 실습 거리로 남겨두겠습니다.
이러한 설정의 또다른 이름은 '프럭시(proxy) ESP'입니다. 이게 다소 뜻이 분명합니다.
주의 IPSEC 터널을 위해선 커널에서 IP 포워딩이 활성화 되어 있어야 합니다.(역자주: '
echo 1 > /proc/sys/net/ipv4/ip_forward ')
7.4. 기타 IPSEC 소프트웨어 ¶Thomas Walpuski는 자신이 OpenBSD의 isakmpd를 리눅스 2.5의 IPSEC과 동작하도록 하는 패치를 작성했다고 얘기하고 있습니다. 게다가 메인 isakmpd CVS 저장소는 지금 이 코드를 포함하고 있습니다!
![]() ![]() isakmpd는 위에서 언급한 racoon과는 꽤 다르며, 많은 사람들이 이 프로그램을 좋아합니다.
![]() ![]() ![]() ![]() 더불어, FreeS/WAN 사용자 공간 도구들을 리눅스 2.5의 자체적인 IPSEC과 동작하도록 만드는 패치가 있습니다.
![]() 7.5.1. Windows ¶Andreas Jellinghaus<
![]() 7.5.2. Check Point VPN-1 NG ¶Peter Bieringer의 보고:
Here are some results (tunnel mode only tested, auth=SHA1): DES: ok 3DES: ok AES-128: ok AES-192: not supported by CP VPN-1 AES-256: ok CAST* : not supported by used Linux kernel Tested version: FP4 aka R54 aka w/AI ![]() 8. 멀티캐스팅 라우팅 ¶FIXME: 담당자 없음!
Multicast-HOWTO는 (상대적으로 말해서) 옛날의 내용이며 그로 인해 부정확하거나 오해를 불러 일으킬 수 있습니다.
멀티캐스트 라우팅(multicast routing)을 할 수 있으려면, 자신이 원하는 멀티캐스트 라우팅 종류를 지원하도록 리눅스 커널을 구성해 주어야 합니다. 이를 위해선 어떤 종류의 멀티캐스트 라우팅을 사용하기를 바라는지 결정해야 합니다. 기본적으로 네 가지의 "일반적인" 종류들이 있습니다.
![]() ![]() ![]() 리눅스 커널에서는 이런 옵션들이 안 보인다는 걸 알 수 있을 것입니다. 이는, 프로토콜 자체는 Zebra나 mountd, pimd 같은 라우팅 응용 프로그램이 다루는 것이기 때문입니다. 하지만 그렇다고 해도, 커널 내에서 올바른 옵션을 선택하기 위해선 어떤 프로토콜을 사용할 것인지 잘 알고 있어야 합니다.
모든 멀티캐스트 라우팅에 대해서 "multicasting" 및 "multicast routing"을 (역자주:
CONFIG_IP_MULTICAST 및 CONFIG_IP_MROUTE ) 활성화 시켜주어야 하는 건 분명합니다. DVMRP 및 MOSPF의 경우는 이걸로 충분합니다. PIM을 사용할 거라면, 접속하려는 네트워크가 PIM 프로토콜의 버전 1과 2중 어느 걸 사용하는가에 따라 PIMv1 또는 PIMv2를 활성화 시켜주어야 합니다.
선택을 마치고 새로운 리눅스 커널을 컴파일 하고 나면 이제 부팅 때 나열되는 IP 프로토콜에
![]() 지금까지는 그럭저럭 좋습니다. 우리는 멀티캐스팅을 활성화 시켰습니다. 이제 우리는 리눅스 커널에게 실제로 뭔가를 하도록 해서, 라우팅을 시작할 수 있어야 합니다. 이는 라우터 테이블에 멀티캐스트 가상 네트워크를 추가해 주는 걸 뜻합니다:
ip route add 224.0.0.0/4 dev eth0 (보다시피 eth0에서 멀티캐스팅을 하고 있다고 가정하고 있습니다! 필요하면 원하는 장치 이름을 대신 써주십시오.)
이번엔, 리눅스에게 패킷을 전달하라고(forward) 얘기해 줍니다...
echo 1 > /proc/sys/net/ipv4/ip_forward 이 시점에서, 이렇게 해준 게 뭔가 하는 건지 궁금할 수도 있겠네요. 그럼, 연결을 테스트 해보기 위해 기본 그룹인 224.0.0.1로 핑을 날려서 뭔가 살아있는지 확인해 보도록 합시다. LAN 상에 있는 멀티캐스팅을 활성화 한 모든 장비들이 응답 해야 하며, 그게 전부입니다. 응답한 장비들 중 어느 것도 224.0.0.1이라는 IP 주소를 가지고 있지 않다는 걸 알 수 있을 것입니다. 놀랍군요!
![]() ping -c 2 224.0.0.1 이제 실제 멀티캐스트 라우팅을 할 준비가 되었습니다. 자, 두 개의 네트워크가 있고 그 사이에서 라우팅을 해줘야 한다고 가정해 보도록 하겠습니다.
(다음 이 시간에...)
9. 대역폭 관리를 위한 큐잉 큐칙 ¶그런데, 이걸 발견했을 때 난 정말로 뿅갔습니다. 리눅스 2.2/2.4에는 고급 전용 대역폭 관리 시스템과 비견할 만한 방식으로 대역폭을 관리할 수 있는 모든 것들이 있습니다.
리눅스는 심지어 Frame이나 ATM이 제공하는 것 이상으로 해주기도 합니다.
혼란을 방지하기 위해 말해두자면,
tc 는 대역폭을 명시할 때 다음 규칙을 사용합니다:
mbps = 1024 kbps = 1024 * 1024 bps => byte/s mbit = 1024 kbit => kilo bit/s. mb = 1024 kb = 1024 * 1024 b => byte mbit = 1024 kbit => kilo bit.내부적으로는 숫자가 bps 및 b로 저장됩니다. 하지만
tc 가 속도를 출력할 때는 다음 규칙을 사용합니다:
1Mbit = 1024 Kbit = 1024 * 1024 bps => byte/s 9.1. 큐와 큐잉 규칙에 대한 설명 ¶큐잉(queueing)을 통해 우리는 데이터를 보내는 방식을 결정합니다. 전송하는 데이터만을 셰이핑(shaping) 할 수 있음을 꼭 알고 있어야 합니다.
인터넷이 동작하는 방식에서 우리는 사람들이 우리에게 보내는 것에 대해선 직접적인 제어권이 없습니다. 이건 집에 있는 (물리적인!) 편지함과 다소 비슷합니다. 세상 전체에 영향을 줘서 사람들이 당신에게 보내는 메일의 양을 바꿀 수 있는 방법은 없습니다. 모두에게 연락을 하는 것조차도 불가능합니다.
하지만 인터넷은 대부분 TCP/IP에 기반하고 있고, 여기에는 우리를 도와주는 특성들이 몇 가지 있습니다. TCP/IP는 두 호스트 사이의 네트워크의 용량을 알 수 있는 방법이 없어서, 일단 데이터를 조금씩 더 빠르게 보내다가('slow start') 보낼 공간이 없어서 패킷이 유실되기 시작하면 그때 속도를 늦추게 됩니다. 실제로는 이것보다는 좀 더 똑똑하게 동작하지만, 거기에 대해선 나중에 다루겠습니다.
이건, 당신에게 온 편지의 절반을 읽지 않고서 사람들이 당신에게 편지를 보내는 걸 멈춰 주길 바라는 것과 동일합니다. 차이가 있다면 인터넷에서는 이게 동작한다는 거지요:-)
라우터를 하나 가지고 있는데 네트워크 내의 특정 호스트들이 너무 빠르게 내려받기를 하는 걸 막고 싶다면, 라우터의 *안쪽* 인터페이스에 대해서 셰이핑을 해주어야 합니다. 라우터가 그 컴퓨터들에게 데이터를 보내는 인터페이스 말입니다.
또한 분명하게 링크의 병목을 제어해야 합니다. 100Mbit NIC를 가지고 있고 256kbit 링크가 있는 라우터가 있다면, 처리할 수 있는 이상의 데이터를 라우터에게 보내지 않도록 해야 합니다. 그러지 않으면 바로 라우터가 링크를 제어하고 가용 대역폭을 셰이핑 하게 됩니다. 말하자면 '큐를 소유'해야 하고, 연속된 링크 내에서 가장 느린 링크가 되어야 합니다. 다행히도 이는 쉽게 가능합니다.
9.2. 단순한, 클래스 없는 큐잉 규칙 ¶말했듯이, 큐잉 규칙을 통해 데이터가 전달되는 방법을 바꾸게 됩니다. 클래스 없는 큐잉 규칙은 일단 데이터를 받아들이고서 이를 다시 스케줄링 하거나, 지연하거나, 차단하기만 하는 규칙입니다.
이러한 규칙들은 더 나누는 것 없이 전체 인터페이스에 대한 트래픽을 셰이핑 하는 데에 쓰일 수 있습니다. 클래스 있는 qdisc를담고있는qdisc 얘기로 진행하기 전에 큐잉의 이 부분을 이해해 두는 것이 아주 중요합니다!
무엇보다 가장 널리 쓰이는 규칙은 pfifo_fast qdisc입니다. 이 규칙이 기본값입니다. 이 규칙은 또한 왜 이런 고급 기능들이 이렇게 탄탄하게 동작하는지를 설명해 줍니다. '그냥 또다른 큐' 이상이 아니기 때문입니다.
이들 큐 각각은 나름의 강점과 약점을 가지고 있습니다. 이것들 모두를 테스트까지 해보지는 않았습니다.
9.2.1. pfifo_fast ¶이 큐는, 그 이름이 말해주듯, First In, First Out입니다. 즉, 어떤 패킷도 특별 대우를 받지 않습니다. 최소한, 많이는 아닙니다. 이 큐는 3개의 소위 말하는 '밴드(band)'를 가지고 있습니다. 각 밴드 내에서 FIFO 규칙이 적용됩니다. 그런데, 밴드 0 내에 대기중인 패킷이 있는 동안은 밴드 1이 처리되지 않습니다. 밴드 1과 밴드 2에 대해서도 마찬가지입니다.
커널은 패킷 내의 소위 Type of Service 플래그를 존중하며, '지연 최소화' 패킷을 신경써서 밴드 0에 집어넣어 줍니다.
이 클래스 없는 단순한 qdisc를 클래스 있는 PRIO qdisc와 혼동하지 마십시오! 유사하게 행동하기는 하지만, pfifo_fast는 클래스가 없어서
tc 명령으로 다른 qdisc를 추가해 줄 수 없습니다.
9.2.1.1. 매개변수 및 사용법 ¶기본값이기에 pfifo_fast qdisc를 따로 구성하는 건 불가능합니다. 기본적으로 구성되어 있는 방식은 다음과 같습니다.
priomap
커널이 할당해 준 패킷 우선순위가 어떻게 밴드로 사상되는지 결정합니다. 다음과 같이 생긴 패킷의 TOS 바이트에 기반해서 사상이 일어납니다:
txqueuelen
0 1 2 3 4 5 6 7 +-----+-----+-----+-----+-----+-----+-----+-----+ | | | | | PRECEDENCE | TOS | MBZ | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+TOS 4비트('TOS 필드')는 다음과 같이 정의되어 있습니다: 이진수 십진수 의미 ----------------------------------------- 1000 8 지연 최소화 (md) 0100 4 처리율 최대화 (mt) 0010 2 신뢰도 최대화 (mr) 0001 1 금전 비용 최소화 (mmc) 0000 0 정상 서비스이 4개 비트 오른쪽에 비트 1개가 더 있기 때문에 TOS 필드의 실제 값은 TOS 비트 값의 2배입니다. tcpdump -v -v 를 하면 4개 비트가 아닌 전체 TOS 필드의 값이 표시됩니다. 바로 아래 표의 첫 번째 열에 있는 값입니다.
TOS 비트 의미 리눅스 우선순위 밴드 ------------------------------------------------------------ 0x0 0 정상 서비스 0 Best Effort 1 0x2 1 금전 비용 최소화(mmc) 1 Filler 2 0x4 2 신뢰도 최대화(mr) 0 Best Effort 1 0x6 3 mmc+mr 0 Best Effort 1 0x8 4 처리율 최대화(mt) 2 Bulk 2 0xa 5 mmc+mt 2 Bulk 2 0xc 6 mr+mt 2 Bulk 2 0xe 7 mmc+mr+mt 2 Bulk 2 0x10 8 지연 최소화(md) 6 Interactive 0 0x12 9 mmc+md 6 Interactive 0 0x14 10 mr+md 6 Interactive 0 0x16 11 mmc+mr+md 6 Interactive 0 0x18 12 mt+md 4 Int. Bulk 1 0x1a 13 mmc+mt+md 4 Int. Bulk 1 0x1c 14 mr+mt+md 4 Int. Bulk 1 0x1e 15 mmc+mr+mt+md 4 Int. Bulk 1숫자들이 참 많습니다. 두 번째 열의 값은 해당하는 TOS 4비트이고, 그 다음 열은 해석한 의미입니다. 예를 들어, 15는 금전 비용 최소화, 신뢰도 최대화, 처리율 최대화, 거기다가 지연 최소화를 원하는 패킷을 나타냅니다. 전 이걸 '쪽바리 패킷(Dutch Packet)'이라고 부릅니다. 네 번째 열에는 리눅스 커널이 TOS 비트를 해석하는 방식을 나열하고 있습니다. TOS 비트가 어떤 우선순위로 사상되는지 볼 수 있습니다. 마지막 열은 기본 priomap의 결과를 보여줍니다. 명령행에서 보면 기본 priomap은 이렇게 보입니다: 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1예를 들면, 우선순위 4가 밴드 번호 1로 사상된다는 의미입니다. priomap에서는 TOS 사상에는 대응하지 않지만 다른 방법으로 설정 가능한 높은 우선순위(> 7)를 나열할 수도 있습니다. RFC 1349(자세한 내용은 읽어보십시오)에서 가져온 다음 표는 응용 프로그램들이 자신의 TOS 비트를 어떻게 설정할 수 있는가에 대한 것입니다. TELNET 1000 (지연 최소화) FTP Control 1000 (지연 최소화) Data 0100 (처리율 최대화) TFTP 1000 (지연 최소화) SMTP Command phase 1000 (지연 최소화) DATA phase 0100 (처리율 최대화) Domain Name Service UDP Query 1000 (지연 최소화) TCP Query 0000 Zone Transfer 0100 (처리율 최대화) NNTP 0001 (금전 비용 최소화) ICMP Errors 0000 Requests 0000 (대부분) Responses <요청과 동일> (대부분) 이 큐의 길이는,
ifconfig 과 ip 로 보고 바꿀 수 있는, 인터페이스 설정에서 가져옵니다. 큐 길이를 10으로 설정하려면 이렇게 실행하십시오: ifconfig eth0 txqueuelen 10
tc 로는 이 매개변수를 바꿀 수 없습니다!
9.2.2. Token Bucket Filter ¶토큰 버킷 필터(TBF)는 간단한 큐구조로서, 설정된 전송률을 초과하는 패킷을 보내지 않도록 하는 큐구조입니다. 그러나, 순간적으로 이 전송률를 초과하는 짧은 버스트(패킷이 빨리 연속되는 경우)의 경우에는 패킷을 전달합니다.
TBF는 매우 정밀하며, 네트웍과 프로세서에 많이 사용됩니다. 만약 여러분이 인터페이스의 속도를 느리게 낮추고자 한다면, 이 큐구조를 먼저 선택할 수 있습니다.
TBF의 구현은 버퍼(버킷, bucket-
token(토큰) 이라고 불리우는 가상적인 조각들에 의해 채워지는 바구니)와 정해진 토큰 발생률(token rate)로 구성됩니다. 버킷의 가장 중요한 파라메터는 그것의 크기이며, 토큰을 담을 수 있는 개수로 표시할 수 있습니다.
토큰이 쌓이면서 패킷이 도착 하기를 기다리고, 이것은 곧 버킷으로부터 지워집니다. 토큰과 데이터의 두 흐름을 연계하면, 다음과 같은 세가지 시나리오를 생각해 볼 수 있습니다.
토큰이 버킷에 쌓이는 것은 순간적으로 빠르게 데이터가 도착할 경우의 손실을 피하기 위해서 필요합니다. 그러나, 계속적인 부하는 패킷 지연을 야기할 것이고, 곧 손실될 것입니다.
9.2.2.1. 파라메터 & 사용법 ¶여러분이 파라메터를 변경할 필요가 없을 수도 있지만, TBF는 몇가지 설정가능한 파라메터가 있습니다.
limit 또는 latency
Limit는 토큰이 사용가능하게 되기를 기다리는 바이트 수를 말합니다. 여러분은 latency 파라메터를 세팅하는 방법을 사용할 수 있습니다. latency 파라메터는 TBF내에 패킷이 기다리는 최대 시간을 명시합니다. 이것은 버킷크기와 토큰발생률 그리고 피크율(만약 세팅한 경우)를 고려하게 됩니다.
burst/buffer/maxburst
버킷의 크기(바이트 단위). 이것은 한번에 사용가능한 토큰의 최대 총 바이트수입니다. 일반적으로, 큰 쉐이핑율(shaping rate)의 경우에는 큰 버퍼를 요구합니다. 만약 10Mbps의 경우, 여러분은 적어도 10k바이트 버퍼가 필요합니다.
만약 버퍼가 너무 작으면, 패킷은 손실될 수 있습니다. 왜냐하면, 버킷에 들어갈 수 있는 토큰수보다 더 많은 토큰이 필요하기 때문입니다.
mpu
0 크기의 패킷이 대역폭 0을 차지하는 것은 아닙니다. 이더넷의 경우, 64바이트보다 작은 패킷은 없습니다. 최소 패킷 단위는 한 패킷에 대한 최소 토큰을 결정합니다.
rate
속도를 말합니다. 앞에서 말한 limit를 보십시오.
만약 버킷이 토큰을 담고 있다가 비우는 경우, 기본적으로 무한대 속도로 수행됩니다. 만약 이것을 적용할 수 없는 경우에는 다음 두 파라메터를 사용하십시오.
peakrate
토큰이 사용가능하고 패킷이 도착할 경우, 패킷은 즉시(흔히 말하는 광속으로) 전송됩니다. 그러나 실제로는 그렇지 않을 수 있습니다.
peakrate는 얼마나 빨리 버킷을 비울 수 있는지를 설정합니다. 정확하게는, 패킷을 쫙보낸다음, 좀 있다가, 다음 것을 쫙보냅니다. 계산할때는 peakrate로 보내는 것으로 합니다.
그러나, Unix의 기본 10ms타이머 때문에, 10,000비트 평균 패킷들에 대해, 1Mbps로 reakrate가 제한됩니다.
mtu/minburst
1Mbps peakrate는 대역폭이 클 경우에는 매우 유용하지 못합니다. 더 큰 peakrate는 timertick당 여러개의 패킷을 보내는 방법으로 가능하다. 이것은 두번째 버킷을 사용하여 동작하도록 하였습니다.
이 두번째 버킷은 사실은 버킷이 아니고 기본적으로 하나의 패킷크기입니다.
최대 가능 peakrate를 계산하려면, 설정된 mtu에 100을 곱합니다. (또는 더 정확하게 HZ값 - Intel의 경우 100, Alpha칩의 경우 1024)
9.2.2.2. 예제 설정 ¶간단하지만 유용한 설정이 여기 있습니다.:
# tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540 그렇습니다. 왜 이것이 유용할까요? 만약 여러분이 큰 큐를 가지고 있는 네트워킹 장치(예를 들면 DSL 모뎀 또는 케이블 모뎀)를 가지고 있고, 이더넷 인터페이스 같은 빠른 장치를 통해 통신한다면, 업로딩이 상호동작을 망가뜨리는 것을 알 수 있을 것입니다.
이것은 업로딩이 모뎀에서 큐를 가득 채우기 때문입니다. 이 큐는 아마도 매우 클 것입니다. 왜냐하면 더 좋은 Throughput을 얻도록 되어 있기 때문입니다. 그러나, 여러분은 이러한 것을 원하지 않을 것입니다. 여러분은 데이터를 보내는 동안 다른 동작을 할 수 있도록 큐가 너무 크지 않기를 원합니다.
그래서 저 위의 예제는 전송속도를 낮추어서 모뎀에서 패킷이 쌓이지 않도록 합니다. 패킷은 우리의 리눅스내의 큐에서 쌓일 것이며, 이 큐는 우리가 크기를 제어할 수 있습니다.
예제의 220kbit를 실제 업링크 속도로 설정해보세요. 만약 여러분이 매우 빠른 모뎀을 가지고 있다면, burst를 좀 올려보십시오.
9.2.3. Stochastic Fairness Queuing ¶SFQ는 fair queueing 알고리즘들 중에 간단한 구현입니다. 이것은 다른 것들보다는 정확하지는 않지만, 계산량이 적습니다.
SFQ의 핵심어는 conversation 또는 flow입니다. 이것은 보통 TCP session 이나 UDP stream에 부합합니다. 트래픽은 매우 많은 FIFO큐로 나뉩니다. FIFO큐 하나는 conversation하나를 담당합니다. 트래픽은 한턴에 한번씩 기회를 얻는 라운드 로빈(round robin) 방식으로 보내집니다.
이것은 매우 공평한 동작을 하도록 하며, 어떤 하나의 conversation이 다른 것들을 망가뜨리는 것을 막습니다. SFQ는 "확률적"이라고 불리우는 이유는 각 세션에 대해 실제로 큐를 할당하지는 않기 때문입니다. SFQ는 해싱알고리즘을 사용하여 트래픽들을 제한된 수의 큐로 분류를 하는 알고리즘을 사용합니다.
해쉬를 사용하기 때문에, 여러개의 세션들이 동일한 큐로 들어갈 수 있습니다. 이는 각 세션의 패킷을 보내는 기회가 나뉘어지게 되며, 결국 실제 속도도 나뉘어지게 됩니다. 이러한 것이 티가 나는 것을 피하기 위하여, SFQ는 해쉬알고리즘을 자주 바꿉니다. 그래서 어떤 두 개의 세션이 수초 정도 내에서만 같이 있게 됩니다.
여러분의 outgoing 인터페이스가 실제로 full이 날 경우에 SFQ가 유용하다는 사실은 중요합니다. 만약 그렇지 않다면, 리눅스에는 패킷이 큐되지 않을 것이고, SFQ는 효과가 없을 것입니다. 양쪽 상황에서 쓸수 있도록 SFQ를 다른 큐구조와 같이 쓰는 것을 나중에 설명할 것입니다.
특별히, 케이블 모뎀이나 DSL라우터에 연결되어 있는 이더넷 인터페이스에, 추가적인 shaping없이, SFQ를 설정하는 것은 무의미합니다.
9.2.3.1. 파라메터 & 사용법 ¶SFQ는 자체 튜닝을 합니다.
perturb
hashing을 다시할 주기를 초단위로 설정합니다. 만약 이것이 설정되지 않으면, 해쉬를 변경하지 않습니다. 이렇게 쓰는 것을 추천하지 않습니다. 10초 정도가 아마도 적절한 값이 될 것입니다.
quantum
다음 큐로 넘어가기 전에 허락되는 큐에서 꺼내는 바이트 수를 설정합니다. 기본값은 MTU 바이트 값입니다. MTU보다 작은 값을 설정하지 마십시오.
limit
SFQ에 의해 큐되는 패킷의 최대 개수를 말합니다. 이 개수를 넘어서는 경우 패킷을 폐기됩니다.
9.2.3.2. 예제 설정 ¶만약 여러분의 장치가 실제 대역폭과 동일한 경우, 즉 전화 모뎀 같은 경우, 다음 설정은 공평성을 갖게 하는데 도움이 됩니다.
# tc qdisc add dev ppp0 root sfq perturb 10 # tc -s -d qdisc ls qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec Sent 4812 bytes 62 pkts (dropped 0, overlimits 0) 숫자
800c: 는 자동으로 할당된 핸들 번호입니다. limit는 128패킷이 이 큐에 들어갈 수 있음을 나타냅니다. 1024해쉬 버킷들이 계산에 사용되며, 이 중에서 128개가 사용되는 것을 의미합니다. 매 10초마다, 해쉬를 다시 구성합니다.
9.3. 각 큐를 사용할때 필요한 조언 ¶요약하자면, 앞의 단순한 큐들은 재정렬, 느리게하기 또는 패킷을 버림으로서 실제로 통행량을 관리한다.
아래에 사용할 큐를 결정하는데 도움이 될만한 몇가지가 있다. 또 14장에서 설명하는 몇가지 큐잉 규칙에 대해서 이야기 할것이다.
13. 커널 네트워크 매개변수 ¶커널은 다양한 환경에 맞게 조정할 수 있는 매개변수들을 다수 가지고 있습니다. 물론 보통 그렇듯, 기본적인 매개변수들로도 99%의 설치 환경에서는 충분합니다만, 우리가 괜히 이 글을 Advanced HOWTO라고 하는 건 아니잖습니까!
흥미로운 것들이
/proc/sys/net 내에 있으니 한번 둘러 보십시오. 모든 내용들이 처음부터 여기에 기록되지는 않겠지만, 계속 작업을 해 나갈 것입니다.
한편 리눅스 커널 소스를 살펴보고 싶을 수도 있을 텐데,
Documentation/filesystems/proc.txt 파일을 읽어보도록 하십시오. 대부분의 내용들이 거기에 설명되어 있습니다.
(FIXME)
13.1. 역경로 필터링(Reverse Path Filtering) ¶기본적으로 라우터는 뭐든지, 심지어 '분명히' 당신의 네트워크에 속하지 않는 패킷까지도 라우팅 합니다. 쉬운 예로 사설 IP 공간이 인터넷으로 빠져나가는 걸 들 수 있습니다. 어떤 인터페이스로 195.96.96.0/24라는 라우트가 있다면 그 인터페이스에 212.64.94.1에서 온 패킷이 도착할 거라고는 생각하지 않습니다.
많은 사람들이 이러한 특성을 끌 수 있기를 원하기에 커널 해커들이 쉽게 그렇게 할 수 있도록 해두었습니다.
/proc 내에는 커널에게 그렇게 하라고 할 수 있는 파일들이 있습니다. 그러한 방법을 "역경로 필터링"이라고 합니다. 기본적으로 패킷에 대한 응답이 그 패킷이 들어온 인터페이스로 나가지 않을 것 같으면 이 패킷은 가짜 패킷인 것이고, 따라서 무시됩니다.
다음 명령은 현재와 미래의 모든 인터페이스에 대해 이 방법을 적용해 줍니다.
# for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do > echo 2 > $i > done위에서의 예를 가지고 하자면, 리눅스 라우터의 eth1에 도착한 패킷이 자기가 사무실+ISP 서브넷에서 왔다고 주장하면 그 패킷은 사라집니다. 마찬가지로 사무실 서브넷에서 패킷이 왔는데 자신이 방화벽 밖의 어딘가에서 왔다고 주장하면 마찬가지로 사라지게 됩니다. 위에 있는 건 전체 역경로 필터링입니다. 기본적인 동작은 직접 연결되어 있는 네트워크의 IP 주소에 기반해서 필터링 하는 것뿐입니다. 전체 필터링을 비대칭 라우팅의 경우 문제가 될 수 있습니다. (비대칭 라우팅은 위성 통신에서처럼 한 쪽으로 패킷이 들어오고 다른 쪽으로 패킷이 나갑니다. 네트워크에서 동적 라우팅(bgp, ospf, rip)을 하는 경우도 마찬가지입니다. 위성 통신의 경우 위성 접시를 통해 데이터가 내려오고 정상적인 지상 회선을 통해 응답이 돌아갑니다.)
이러한 예외적인 경우가 자신에게 해당된다면 (그렇다면 이미 본인이 그걸 알고 있을 겁니다.) 위성 데이터가 들어오는 인터페이스에서 rp_filter를 꺼주면 됩니다. 패킷이 사라지고 있는지 알고 싶은 경우 같은 디렉터리 내의 log_martians 파일이 커널이 그런 패킷들을 syslog에 기록하도록 해줍니다.
# echo 1 >/proc/sys/net/ipv4/conf/<interfacename>/log_martiansFIXME: conf/{default,all}/* 파일들을 설정하면 충분하지 않나요? - martijn (역자주: 충분하지 않습니다. conf/all/* 파일은 동작에 영향을 주지 않으며, 인터페이스별 디렉터리 내의 파일을 직접 조작해 주어야 합니다.)
13.2. 숨겨진 설정들 ¶자, 변경할 수 있는 매개변수들이 참 많이 있습니다. 모두를 나열해 볼 것입니다. 이는 Documentation/ip-sysctl.txt에(역자주: Documentation/networking/ip-sysctl.txt가 정확한 경로입니다.) (일부) 문서화 되어 있습니다.
이 설정들 중 몇몇은 커널을 컴파일 할 때 '호스트 대신 라우터로 구성하기'(역자주: NETFILTER, IP_ADVANCED_ROUTER 등)에 'Yes'로 대답했는가에 따라서 다른 기본값을 가집니다.
Oskar Andreasson 역시도 이 플래그들 전부에 대한 페이지를 가지고 있으며 우리 것보다 더 나은 것 같으니,
![]() 13.2.1. ipv4 일반 ¶일반적으로 주의할 것은 대부분의 속도 제한 기능이 루프백에서는 동작하지 않는다는 것입니다. 그러니 로컬에서 테스트 하지 마십시오. 제한은 'jiffy' 단위이며 앞서 언급한 토큰 버킷 필터를 사용해 적용됩니다.
커널은 초당 'HZ' 번(혹는 HZ 'jiffies' 만큼) 똑딱이는 내부 시계를 가지고 있습니다. Intel의 경우 'HZ'는 대부분 100입니다. 따라서 *_rate 파일을 50으로 설정하면 초당 2개 패킷을 허용하게 됩니다. 토큰 버킷 필터는 충분한 토큰을 모은 경우 최대 6개 패킷까지 집중되는 걸 허용합니다.
다음 목록의 몇몇 항목은 Alexey Kuznetsov <
![]() ![]()
13.2.2. 장치별 설정 ¶DEV는 실제 인터페이스, 또는 'all(전체)'이나 'default(기본값)'을 나타냅니다. 기본값은 또한 생성될 인터페이스에 대한 설정을 바꿔줍니다.
13.2.3. 이웃(neighbor) 정책 ¶DEV는 실제 인터페이스, 또는 'all(전체)'이나 'default(기본값)'을 나타냅니다. 기본값은 또한 생성될 인터페이스에 대한 설정을 바꿔줍니다.
13.2.4. 라우팅 설정 ¶
14.1. bfifo/pfifo ¶bfifo와 pfifo는 클래스없는(classless) 큐구조로, 내부적인 밴드를 갖는 pfifo_fast보다더 단순한 것이다. 즉, 모든 트래픽이 동일하게 취급된다. 이 구조들은 하나의 중요한 장점을 갖는데, 바로 어떤 통계치를 갖는다는 것이다. 그래서, shaping 또는 prioritizing이 없을 경우에, 여러분의 인터페이스의 backlog(쌓여 있는 패킷 또는 데이터량)를 결정하는데 사용할 수 있습니다.
pfifo는 패킷 개수로 길이를 계산하며, bfifo는 바이트단위로 길이를 계산합니다.
14.1.1. 파라메터 & 사용법 ¶limit
큐의 길이를 명시합니다. bfifo에서는 바이트단위로 계산되며, pfifo에서는 패킷단위로 계산됩니다. 기본값은 인터페이스 txqueuelen 패킷길이가 되며(pfifo_fast 장을 참고), bfifo의 경우에는 txqueuelen*mtu 바이트입니다.
14.6. Generic Random Early Detection ¶GRED에 대해 많이 알려진 것이 없습니다. GRED는 Diffserv tcindex에 기반한 내부적인 큐를 가지고 있습니다.관련된 슬라이드는
![]() FIXME: 추가적인 정보를 Jamal 또는 Werner에게 알려주세요.
(softgear- GRED에 대해서는 http://www.opalsoft.net/qos/DS.htm 에서 더 많은 정보를 얻을 수 있습니다)
14.8. Weighted Round Robin (WRR) ¶이 큐구조는 표준 리눅스 커널에는 포함되어 있지 않지만,
![]() 이 큐구조는 내장 분류자(classifier)를 가지고 있습니다. 이는 다른 클래스나 장비로부터 들어오는 패킷 또는 나가는 패킷에 할당할 수 있습니다. MAC 또는 IP 그리고 source 또는 destination주소를 사용할 수 있습니다. 그러나, MAC주소는 Linux box가 ethernet bridge로 동작할때만 사용할 수 있습니다. 클래스는 패킷에 표시된 장비의 주소에 따라 자동으로 할당됩니다.
이 큐구조는 많은 인터넷 연결이 공유되는 곳에서 유용하게 사용될 수 있습니다. WRR 배포판에는 이러한 곳에서 동작할 수 있는 스크립트들이 포함되어 있습니다.
15.7. Circumventing Path MTU Discovery issues with MSS Clamping (for ADSL, cable, PPPoE & PPtP users) ¶20. Acknowledgements ¶DeleteMe 오래 전에 lartc 번역을 하던 것이 있습니다. 번역의 시작을 kldp 쪽으로 미리 알리지 않고 개인적으로 하던 작업이어서 due 를 두지 않았더니 중단된 상태네요. 지금은 revision 얼마인지 모르겠지만 한 일 년 전의 문서를 기준으로 번역한 것이니 참고하세요. 아래 주소에 있습니다.
번역 작업을 그만둔 이유가.. 아무래도 원문의 맛 그대로를 한국어로 옮긴다는 것은 제 능력으로 무리였다는 점이 가장 크지 않았나 합니다. -- ai
음.. 마무리를 하셨으면 더 좋았을 텐데요.. 그래도 아예 없는 것 보다는 뒷 사람을 위해서라도 하는게 좋죠..
개인적으로 QoS에 대해서 관심이 많아서 이 문서를 보다가 이곳까지 오게 되었습니다. 참.. 힘든작업 하십니다... 워낙 엄청난 자료들이라서.. 개인적으로나마 저도 docbook에 대해 공부를 하고 해석을 해나가 보겠습니다만... 도움이 될지는 미지수 입니다... -_-;; 그럼 수고들 하십시요..
-- SkullQ
![]() 허락도 없이 감히 끼어들었습니다.. 워낙에 번역(?) 해보고 싶던 문서라서요.. 양이 좀 많고 계속해서 업데이트 되고 있는 문서라 중간중간 짬짬이 끼어들게요.. 그리고 LARTC 홈페이지 링크했습니다.. ^^;;; -- scipione 괜찮습니다.. 시작은 ai 님이 먼저 하신거고 전 아직 옮기는 데도 시간이 부족해서 천천히 해 나갈 생각이니 진도가 안나가고 있구나 하고 생각되면 계속 껴들어 주세요..
![]() |
Don't be overly suspicious where it's not warranted. |