· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Linux Advanced Routing & Traffic Control HOWTO


Linux Advanced Routing & Traffic Control HOWTO

옮긴이: 이재광 pulccot(at)unitel.co.kr , 너바나, scipione, softgear(at)dcn.ssu.ac.kr

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 $ $Date: 2006/09/14 15:31:31 $ DocBook Edition



Contents

[-]
1. 헌정
2. 소개
2.1. 권리의 포기와 허가
2.2. 사전 지식
2.3. 리눅스로 할 수 있는 것 들
2.4. 문서에 대해 일러두기
2.5. 접근, CVS와 수정본의 제출
2.6. 메일링 리스트
2.7. 문서의 구조
3. iproute2 소개
3.1. 왜 iproute2 인가 ?
3.2. iproute2 여행
3.3. 준비물
3.4. 현재 설정 살펴보기
3.4.1. ip로 연결(link) 상태 보기
3.4.2. ip 명령으로 IP 주소 보기
3.4.3. ip 명령으로 라우팅 정보 보기
3.5. ARP (Address Resolution Protocol)
4. 규칙들 - 경로배정 정책 데이터베이스 (Routing Policy Database)
4.1. 출처에 따른 단순한 경로 배정 정책
4.2. 여러 상향 경로와 서비스 제공자를 위한 경로 배정
4.2.1. 분리 접근
4.2.2. 부하 분산
5. GRE 와 다른 터널들
5.1. 터널에 대한 몇 가지 이야기
5.2. IP in IP 터널링
5.3. GRE 터널링
5.3.1. IPv4 터널링
5.3.2. IPv6 터널링
5.4. 사용자 영역 터널
6. 시스코 와(또는) 6bone에서 IPv6 터널링
6.1. IPv6 터널링
7. IPSEC: 인터넷 상의 안전한 IP
7.1. 수동 키입력 입문
7.2. 자동 키교환
7.2.1. 이론
7.2.2. 예제
7.2.2.1. 문제점 및 알려진 결함
7.2.3. X.509 인증서를 이용한 자동 키교환
7.2.3.1. 호스트를 위한 X.509 인증서 만들기
7.2.3.2. 설정 및 시동
7.2.3.3. 안전하게 터널을 구성하는 방법
7.3. IPSEC 터널
7.4. 기타 IPSEC 소프트웨어
7.5. 다른 시스템과의 IPSEC 상호 연동
7.5.1. Windows
7.5.2. Check Point VPN-1 NG
8. 멀티캐스팅 라우팅
9. 대역폭 관리를 위한 큐잉 큐칙
9.1. 큐와 큐잉 규칙에 대한 설명
9.2. 단순한, 클래스 없는 큐잉 규칙
9.2.1. pfifo_fast
9.2.1.1. 매개변수 및 사용법
9.2.2. Token Bucket Filter
9.2.2.1. 파라메터 & 사용법
9.2.2.2. 예제 설정
9.2.3. Stochastic Fairness Queuing
9.2.3.1. 파라메터 & 사용법
9.2.3.2. 예제 설정
9.3. 각 큐를 사용할때 필요한 조언
9.4. Terminology
9.5. Classful Queuing Disciplines
9.5.1. Flows within classful qdiscs & classes
9.5.2. The qdisc family: roots, handles, siblings and parents
9.5.3. The PRIO qdisc
9.5.4. The famous CBQ qdisc
9.5.5. Hierarchical Token Bucket
9.6. Classifying packets with filters
9.6.1. Some simple filtering examples
9.6.2. All the filtering commands you will normally need
9.7. The Intermediate Queuing Device (IMQ)
9.7.1. Simple configuration
10. Load sharing over multiple interfaces
10.1. Caveats
10.2. Other possibilities
11. Netfilter & iproute - marking packets
12. Advanced filters for (re-)classifying packets
12.1. The u32 classifier
12.1.1. U32 selector
12.1.2. General selectors
12.1.3. Specific selectors
12.2. The route classifier
12.3. Policing filters
12.3.1. Ways to police
12.3.2. Overlimit actions
12.3.3. Examples
12.4. Hashing filters for very fast massive filtering
12.5. Filtering IPv6 traffic
12.5.1. How come that IPv6 tc filters do not work?
12.5.2. Marking IPv6 packets using ip6tables
12.5.3. Using the u32 selector to match IPv6 packet
13. 커널 네트워크 매개변수
13.1. 역경로 필터링(Reverse Path Filtering)
13.2. 숨겨진 설정들
13.2.1. ipv4 일반
13.2.2. 장치별 설정
13.2.3. 이웃(neighbor) 정책
13.2.4. 라우팅 설정
14. 전문적이고 덜 사용되는 큐 구조들
14.1. bfifo/pfifo
14.1.1. 파라메터 & 사용법
14.2. Clark-Shenker-Zhang algorithm (CSZ)
14.3. DSMARK
14.3.1. Introduction
14.3.2. What is DSMARK related to?
14.3.3. Differentiated Services guidelines
14.3.4. Working with DSMARK
14.3.5. How SCH_DSMARK works
14.3.6. TC_INDEX Filter
14.4. Ingress qdisc
14.4.1. Parameters & usage
14.5. Random Early Detection (RED)
14.6. Generic Random Early Detection
14.7. VC/ATM emulation
14.8. Weighted Round Robin (WRR)
15. Cookbook
15.1. Running multiple sites with different SLAs
15.2. Protecting your host from SYN floods
15.3. Rate limit ICMP to prevent dDoS
15.4. Prioritizing interactive traffic
15.5. Transparent web-caching using netfilter, iproute2, ipchains and squid
15.5.1. Traffic flow diagram after implementation
15.6. Circumventing Path MTU Discovery issues with per route MTU settings
15.6.1. Solution
15.7. Circumventing Path MTU Discovery issues with MSS Clamping (for ADSL, cable, PPPoE & PPtP users)
15.8. The Ultimate Traffic Conditioner: Low Latency, Fast Up & Downloads
15.8.1. Why it doesn't work well by default
15.8.2. The actual script (CBQ)
15.8.3. The actual script (HTB)
15.9. Rate limiting a single host or netmask
15.10. Example of a full nat solution with QoS
15.10.1. Let's begin optimizing that scarce bandwidth
15.10.2. Classifying packets
15.10.3. Improving our setup
15.10.4. Making all of the above start at boot
16. Building bridges, and pseudo-bridges with Proxy ARP
16.1. State of bridging and iptables
16.2. Bridging and shaping
16.3. Pseudo-bridges with Proxy-ARP
16.3.1. ARP & Proxy-ARP
16.3.2. Implementing it
17. Dynamic routing - OSPF and BGP
17.1. Setting up OSPF with Zebra
17.1.1. Prerequisites
17.1.2. Configuring Zebra
17.1.3. Running Zebra
17.2. Setting up BGP4 with Zebra
17.2.1. Network Map (Example)
17.2.2. Configuration (Example)
17.2.3. Checking Configuration
18. Other possibilities
19. Further reading
20. Acknowledgements

1. 헌정


이 문서는 많은 사람들의 열정이자 무언가 보답하고 싶은 나의 노력의 결과물이다. 적은 수나마 나타내면 아래와 같다.

  • Rusty Russell
  • Alexey N. Kuznetsov
  • 구글에 있는 좋은 사람들
  • Casema Internet의 직원들

2. 소개


반갑습니다, 다정한 독자여.

이 문서는 리눅스 2.2/2.4를 가지고 어떻게 많은 것을 할 수 있는지 가르치기를 희망합니다. 많은 사용자들에게는 미지의 것이지만 멋진 일을 하게 해주는 도구들을 이미 실행해 봤을 겁니다. routeifconfig 같은 명령은 사실 매우 강력한 iproute2 인프라를 둘러싼 얇은 껍질에 불과합니다.

나는 이 HOWTO가 Rusty Russell의 것 중 하나 netfilter와 같이 널리 읽히기를 바랍니다.

MHOWTO 팀에게 글을 쓰면 항상 연락할 수 있습니다. 그러나 내용이 이 HOWTO와 직접 연관이 없다면 메일링 리스트(관련 부분을 보시오)에 올리는걸 고려하십시오. 우리는 무료 도우미가 아닙니다, 다만 리스트에 올라온 내용에 대해선 가끔씩 대답을 합니다.

이 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. 사전 지식

제목이 얘기 하는 것처럼 "고급" 하우투다. 로켓 과학을 얘기하는 건 아니지만 약간의 사전 지식이 있다고 가정한다.

여기 도움 줄 수 있는 몇개의 참고 문들을 소개한다.

[http] Rusty Russell's networking-concepts-HOWTO
네트웍이 무엇인가에 대해 매우 훌륭한 소개와 설명이 있고 어떻게 다른 네트웍과 연결되는지 얘기한다.

Linux Networking-HOWTO (전에는 Net-3 HOWTO)
좀 수다드럽지만 대단한 작품이다. 이미 인터넷에 연결되어 있다면 설정해 놓은 많은 것들에 대해서 가르쳐 준다. /usr/doc/HOWTO/NET3-4-HOWTO.txt 여기 있겠지만 온라인에서는 [http]여기에서 찾는다.

2.3. 리눅스로 할 수 있는 것 들

이런일을 할 수 있습니다 :
  • 특정 컴퓨터의 대역폭을 제한합니다.
  • 특정 컴퓨터로 가는 대역폭을 제한합니다.
  • 대역폭을 공평하게 나눠 씁니다.
  • 네트웍을 서비스 거부 공격(DoS attack: Denial of Service attack)에서 보호합니다.
  • 인터넷망을 고객에게서 보호합니다.
  • 고가용성이나 부하분산을 위해 여러 서버를 하나 처럼 보이게 합니다.
  • 컴퓨터에 대한 접근을 제한합니다.
  • 사용자들이 다른 호스트로 접근하는 걸 제한합니다.
  • 사용자별(물론), MAC 주소, 출발지 IP 주소, 포트, 서비스 종류, 시간, 내용에 따라 다르게 라우팅 할 수 있습니다.
현재 적은 사람들이 고급 기능을 사용하고 있습니다. 여기에는 여러 이유가 있습니다. 이유는 여러가지인데, 기존의 문서들이 너무 장황한데다 실제로 써먹을만한 것과는 거리가 멀고, 흐름 조절에 대해서는 거의 설명이 없기 때문입니다.

2.4. 문서에 대해 일러두기

이 문서에 대해 미리 말해두고 싶은 것들이 몇 가지 있습니다. 문서의 대부분은 제가 작성했지만, 계속해서 같은 방법으로 문서를 유지해나가고 싶지는 않습니다. 저는 오픈소스에 대한 강력한 지지자로서 누구든지 이 문서에 대해 피드백을 보내주고, 갱신하거나 수정하는 것에 대해 환영입니다. 오탈자가 있거나 사소하게 잘못된 부분이 있더라도 언제든 제게 알려주십시오. 문체가 어딘지 딱딱하게 느껴진다면 필자가 영어민 아니라서 그러려니 생각해 주십시오. 제안할 내용을 보내는데 부담을 갖지 말아주십시오.

만약 당신이 어떤 섹션을 맡아서 유지하는데 스스로가 더 적당하다고 느끼신다면, 또는 새로운 섹션을 작성해서 유지해나가려고 한다면 그것 또한 환영합니다. 이 하우투의 SGML 판은 CVS 를 통해 구할 수 있습니다. 많은 분들이 이 문서를 협력해서 만들어나갈 수 있다면 정말 좋겠습니다.

덧붙여 이 문서를 읽다보면 많은 FIXME 표시를 보실겁니다. 수정은 언제나 대환영! FIXME 표시가 있는 부분을 읽으신다면 당신은 미지의 영역을 걷고 있는 것입니다. 표시가 붙어있지 않은 다른 부분에서는 오류가 전혀 없다는 의미는 물론 아닙니다만, 그만큼 더 조심해야 된다는 뜻이죠. 만약 어떤 내용에 대해 검증하셨다면 알려주십시오. 그러면 FIXME 표시를 삭제할 것입니다.

이 하우투에서는 몇가지 가정하고 있는 것이 있습니다. 이를테면 실제로는 좀 드물겠지만 인터넷 연결에 10 Mbit 이라든지 하는 내용입니다.

2.5. 접근, CVS와 수정본의 제출

이 HOWTO 문서는 공식적으로 [http]이곳 에서 얻을 수 있습니다.

전 세계 어디서든 익명 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. 메일링 리스트

저자들은 이 하우투에 대해 점점 더 많은 편지를 받게 되었는데, 메일링리스트를 개설하는 것이 모두에게 도움이 될 것이라는 것이 명백하다는 결정에 이르렀습니다. [http]이곳에서 메일링리스트에 가입할 수 있으며, 문서와 관련된 내용에 대해 이야기할 수 있습니다.

메일링리스트를 통하지 않은 질문에 대해서는 저자들이 답하기를 매우 꺼려 할 것이란 것을 지적하고 넘어갑니다. 이는 메일링리스트가 일종의 지식의 주춧돌이 되길 원하기 때문입니다. 만약 질문이 있다면 우선 메일링 저장소를 검색해본 다음에 메일링리스트에 투고해주세요.

2.7. 문서의 구조

우리는 시작부터 재미있는 내용들을 다루게 됩니다. 그래서 처음 이 문서를 읽을 때는 완전히 설명할 수 없는 부분도 있고, 완벽하지 않은 부분도 있습니다. 이런 부분에 대해서는 대충 넘어가십시오. 언젠가 나중에는 모든 것을 이해할 수 있을 겁니다.

라우팅과 필터링은 뚜렷하게 구별되는 두 분류인데, 필터링에 대해서는 Rusty 의 하우투에서 아주 잘 설명하고 있습니다. 여기서 읽어보세요 :

이 문서에서는 netfilter 와 iproute2 를 연동하여 할 수 있는 작업들을 중점적으로 다룹니다.

3. iproute2 소개

3.1. 왜 iproute2 인가 ?

현재 대부분 리눅스 배포본과 유닉스 시스템에서는 arpifconfig, 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" 에서 구할 수 있습니다.

[ftp]이곳에서 최신 버전을 구할 수 있습니다.

일부 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)들이 있지만 당장은 신경쓰지 마십시오.

  • address family에 관한 것은 socket 또는 route 등의 man page를 참고하세요. 보다 확실한것은 socket의 헤더파일을 열어보면 알 수 있습니다.

eth0 을 더 자세히 살펴봅시다. eth0 은 inet 주소 '10.0.0.1/8' 에 연결되어 있다고 나와 있습니다. 무슨 뜻일까요? /8 은 네트웍 주소의 비트 수를 의미합니다. 32비트 중에서 24 비트를 우리 네트웍을 위해 할당합니다. 10.0.0.1 의 처음 8 비트는 10.0.0.0 인데, 이는 네트웍 주소가 되고, 따라서 netmask 는 255.0.0.0 입니다.

남은 비트는 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 는 [http]RFC 826에 설명되어 있는 주소결정 프로토콜입니다. ARP 는 네트웍에 연결된 컴퓨터가 같은 지역 네트웍에 존재하는 다른 컴퓨터의 하드웨어 위치/주소를 알아내는데 사용됩니다. 인터넷 상의 컴퓨터들은 보통 자기 이름이 알려져 있는데, 이 이름은 IP 주소로 해석 할 수 있습니다. 이러한 방법으로 foo.com 네트웍에 있는 컴퓨터는 bar.net 에 있는 다른 컴퓨터와 통신합니다. 하지만 IP 주소는 컴퓨터의 물리적인 위치를 알려주지는 않는데, 여기서 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 reachable
espa041 에서 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 stale
espa041 은 다시 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 네트웍 입니다.

두 개의 경로 배정 표를 추가하고 그 이름을 각각 T1T2 이라고 합니다. 이것은 /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 의 패치를 [http]http://www.linuxvirtualserver.org/~julian/#routes 에서 찾아보시오. 이 패치를 적용하면 좀 더 잘 작동합니다.

5. GRE 와 다른 터널들

리눅스에는 세 가지 종류의 터널이 있습니다. IP in IP 터널링, GRE 터널링, 커널 외부의 터널 (예를 들어 PPTP 와 유사한 것) 이 그것입니다.

5.1. 터널에 대한 몇 가지 이야기

터널을 사용하면 아주 특별하고 대단한 일을 해낼 수 있습니다. 반면 제대로 설정하지 않으면 모든 것을 완전히 망쳐놓을 수 있습니다. 그래서 무엇을 하는지 정확히 이해하지 못하는 분은 절대로 기본 경로를 터널 장치로 하도록 만들지 마십시오. :-) 게다가 터널링은 간접비용을 증가시킵니다. 이것은 IP 머리가 추가되기 때문인데, 일반적으로 패킷당 20 바이트의 크기를 가집니다. 따라서 네트웍의 보통 패킷 크기(MTU)가 1500 바이트 라면 터널을 통과할 수 있는 패킷은 1480 바이트가 한계입니다. 이것이 꼭 문제가 된다는 것은 아니지만, 대규모 네트웍을 터널을 통해 연결시키려고 할 때 IP 패킷의 분할/재조합에 대해 충분히 알고 있지 않으면 곤란합니다. 아, 그리고 터널을 만드는데 가장 빠른 방법은 양쪽에서 같이 파는 것입니다.

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. 시스코 와(또는) 6bone에서 IPv6 터널링

Marco Davids <marco@sara.nl>

관리자에 대한 주의 : 내가 보기엔, 이 IPv6-IPv4터널링은 GRE 터널링의 정의에 관한것이 아닙니다. 당신은 GRE 터널의 일반적인 방법으로 (GRE는 어떤것이라도 IPv4위에 터널을 열수있음) IPv4위에 IPv6를 언는 터널을 했지만 그장치는 오직 IPv4위어 IPv6를 언는 ("sit") 터널로만 사용되었고 그래서 이것은 약간 다른 얘기입니다.

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를 적는것은 큰 짐이 됩니다. 그래서 쉽게 하기 위한 몇가지 규칙이 있습니다:

  • 처음에 오는0을 쓰지 않는다. IPv4도 같습니다.

  • 16비트 혹은 두바이트를 나누기 위해 콜론을 사용합니다.

  • 연속적인 0을 많이 가지고 있으면 :: 쓸 수 있습니다. 주소에서 오직 한번만 쓸 수 있고 적어도 16비트 이상이 되어야 합니다.

주소 2002:836b:9820:0000:0000:0000:836b:9886는 어떤면에서는 친숙하게 2002:836b:9820::836b:9886로 쓸 수 있습니다.

다른 보기는, 주소 3ffe:0000:0000:0000:0000:0020:34A1:F32C는 아주 짧게 3ffe::20:34A1:F32C로 쓸 수 있습니다.

IPv6는 IPv4의 후계자가 되려고 합니다. 왜냐하면 비교적 신기술이고 아직 세계적으로 본래의 IPv6 네트웍이 없기때문입니다. 전환을 빠르게 하려고 6bone이 소개되었습니다.

IPv6 네트웍인 이미 있는 IPv4 인프라를 통해 IPv6 프로토콜을 IPv4 패킷에 싸서 보내는 식으로 연결합니다.

그것이 정확하게 터널에 발을 들여 놓는 것입니다.

IPv6를 사용하기 위해선 커널이 지원하도록 해야 합니다. 그것을 하기위한 만은 문서들이 있습니다. 그러나 그것은 모두 몇단계로 줄일수 있습니다:

  • 적당한 glibc가 있는 리눅스 배포본을 구합니다.

  • 최신 커널 소스를 구합니다.

모두 준비되면, IPv6를 지원하는 커널을 컴파일할 수 있습니다:

  • /usr/src/linux 로 가서 입력합니다 :

  • make menuconfig

  • "Networking Options"를 선택합니다

  • "The IPv6 protocol", "IPv6: enable EUI-64 token format", "IPv6: disable provider based addresses"를 선택합니다

요령: '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 주소처럼 쓰인다는것에 주목해 주십시오.

IPv4 주소는 145.100.24.181 이고 6bone라우터의 IPv4 주소는 145.100.1.5 입니다.

# 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

radvd를 IPv6 관문에 실행하고 지역 LAN에 IPv6를 지원하는 리눅스를 부팅하면 IPv6의 자동 설정의 이점을 즐길 수 있습니다.

# /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

최근에 리눅스에서는 두 가지 종류의 WikiPedia:IPSEC을 사용할 수 있습니다. 2.2 및 2.4에는 WikiPedia:FreeS/WAN이 있는데, 이는 최초의 제대로 된 구현이었습니다. [http]공식 사이트 및 현재도 유지 관리가 이루어지고 있는 [http]비공식 사이트가 있습니다. 전통적으로 FreeS/WAN은 몇 가지 이유로 인해 주류 커널로 통합되지 않았습니다. 가장 많이 언급되는 이유는 미국인이 암호화에 작업을 해서 수출 가능성을 훼손시킨 것과 관련된 '정치적인' 문제입니다. (역자주: 미국의 암호화제품 수출금지법은 어떤 기준 이상의 성능을 가진 암호화 기술을 포함한 제품의 수출을 제한 내지는 금지하고 있습니다.) 게다가, 이 프로그램은 리눅스 커널에 아주 잘 통합되지는 않으며, 이로 인해 실제 합병의 좋은 후보는 되지 못하고 있습니다. (역자주: FreeS/WAN에서 이어진 프로젝트로 [http]Openswan[http]strongSwan이 있습니다.)

더불어, [http]많은 관련인들(역자주: NoSmoke:DeadLink)이코드의 품질에 대해 [http]우려의 목소리(역자주: NoSmoke:DeadLink)를내고 있습니다. FreeS/WAN의 설치를 위한 많은 [http]문서들(역자주: NoSmoke:DeadLink)이 [http]존재합니다.

리눅스 2.5.47의 경우 커널 내에 자체적인 IPSEC 구현이 있습니다. 이는 Alexey Kuznetsov 및 Dave Miller가 [http]USAGI IPv6 그룹의 작업에 영향을 받아 작성한 것입니다. James Morris의 !CryptoAPI도 병합이 이루어져서 커널의 일부가 되었으며, 실제로 암호화를 해 줍니다.

이 HOWTO는 IPSEC의 2.5+ 버전만을 다룰 것입니다. 현재로선 리눅스 2.4 사용자에게 FreeS/WAN을 권하지만, 그 구성이 자체적인 IPSEC의 경우와는 다를 것이란 점을 염두에 두어야 합니다. 관련 소식에 따르면 현재 FreeS/WAN의 사용자공간 코드를 자체적인 리눅스 IPSEC과 함께 동작하도록 해 주는 [http]패치들이 있다고 합니다.

2.5.49의 경우 IPSEC은 추가적인 패치 없이도 동작합니다.

주의 사용자 공간 도구들은 [http]여기에 있는 듯 합니다. 다양한 프로그램들이 존재하며, 여기에 링크된 건 Rocoon에 기반한 것입니다.

커널을 컴파일 할 때 'PF_KEY'와 'AH', 'ESP', 그리고 CryptoAPI 안에 있는 모든 것들을 켜주는 걸 잊지 마세요!

경고 이 장의 저자는 제대로된 IPSEC 바부탱입니다! 없을 리가 없는 실수들을 찾게 되면 bert hubert<Mahu@ds9a.nl>에게 메일을 날려 주십시오.

첫 번째로는, 두 호스트 간에 수동으로 보안 통신을 설정하는 법을 보일 것입니다. 이 과정의 상당 부분은 자동화 될 수도 있습니다만, 여기서는 '아랫 동네에서' 진행되는 일들에 익숙해 질 수 있도록 하기 위해 직접 해 보도록 하겠습니다.

자동 키교환에만 관심이 있다면 다음 절을 건너뛰어도 무방합니다만, 수동 키입력(역자주: manual keying은 '수동 키입력'으로, automatic keying은 '자동 키교환'으로 번역합니다)을 어느 정도 이해하는 게 유용하다는 건 알고 계시길 바랍니다.

7.1. 수동 키입력 입문

IPSEC은 복잡한 주제입니다. 많은 정보들이 온라인 상에 있으며, 이 HOWTO는 여러분들이 걸음마를 뗄 수 있도록 하는 것과 기본적인 원리들을 설명하는 것에 집중할 것입니다. 모든 예제들은 위에서 얘기한 링크에 있는 Rocoon에 기반하고 있습니다.

주의 많은 iptables 구성들은 IPSEC 패킷을 차단시킵니다! IPSEC을 통과시키려면: 'iptables -A xxx -p 50 -j ACCEPT' 및 'iptables -A xxx -p 51 -j ACCEPT'

IPSEC은 InternetProtocol의 보안 버전을 제공해 줍니다. 이 맥락에서 보안이란 암호화(encryption)와 인증(authentication)이라는 상이한 두 가지를 뜻합니다. 보안에 대한 얕은 시각으로는 암호화만을 얘기할 수도 있겠지만, 그것만으로는 충분치 않다는 걸 쉽게 알 수 있습니다. 암호화를 해서 통신을 하고 있다고 해도, 원격지의 상대가 자신이 예상하고 있는 그 사람인지는 보장되지 않습니다.

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 구현은 [http]KAME 'racoon' WikiPedia:IKE데몬과 함께 동작합니다. 11월 9일 현재, Alexey의 iptools 배포판은 두 개의 파일에서 #include <net/route.h>를 제거해 줘야 할 수도 있기는 하지만, 컴파일이 가능합니다. 대신 제가 제공하는 [http]미리 컴파일된 버전도 있습니다.

노트 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 인증서 만들기
[http]OpenSSL은 인증 기관(certificate authority)이 서명을 할 수도 있고 아닐 수도 있는 키들에 대한 풍부한 기반 구조를 가지고 있습니다. 일단 우리는 그 기반 구조 모두를 뒤로 하고, 꽤 괜찮은 고전적인 Snake Oil 보안을, 인증 기관 없이 실습해야 합니다.

먼저 우리는 '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_methodrsasig인 걸 제외하고는 앞서 본 것과 다르지 않습니다. 그 줄은 인증을 위해 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

이제 우리가 해야 할 일이란 원격지의 상대가 동일한 다이제스트를 보는지 확인하는 것입니다. 이는 실제 삶에서 만나는 식으로도 가능하겠고, 전화를 통해서도 가능한데, 이때는 원격 상대의 전화 번호가 키를 담고 있던 이메일에서 함께 보내지지는 않았는지 확인해야 합니다!

이를 위한 또다른 방법은 인증 기관을 운영하는 신뢰하는 제삼자(WikiPedia:Trusted_third_party)를이용하는 것입니다. 앞서 우리가 직접 했던 키에 대한 서명을 이 CA가 해줄 것입니다.

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 저장소는 지금 이 코드를 포함하고 있습니다! [http]그의 페이지(역자주: NoSmoke:DeadLink)에몇 가지 설명들이 있습니다.

isakmpd는 위에서 언급한 racoon과는 꽤 다르며, 많은 사람들이 이 프로그램을 좋아합니다. [http]여기에서 찾을 수 있습니다. OpenBSD CVS에 대해서 더 읽으려면 [http]여기를 보십시오. Thomas는 또한 CVS나 패치에 능숙하지 않은 사람들을 위해 [http]타르볼(역자주: NoSmoke:DeadLink)을만들어 두기도 했습니다.

더불어, FreeS/WAN 사용자 공간 도구들을 리눅스 2.5의 자체적인 IPSEC과 동작하도록 만드는 패치가 있습니다. [http]여기에서 찾을 수 있습니다.

7.5. 다른 시스템과의 IPSEC 상호 연동

FIXME: 작성 필요

7.5.1. Windows

Andreas Jellinghaus<Maj@dungeon.inka.de>의 보고: "win2k: 동작합니다. 인증을 위해 사전 공유키와 ip 주소를 사용했습니다(윈도우가 fqdn이나 userfqdn 문자열을 지원하는 것 같지는 않네요). 인증서도 분명 동작할 텐데, 해보지는 않았습니다."

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

[http]여기에 추가 정보가 있습니다.

8. 멀티캐스팅 라우팅

FIXME: 담당자 없음!

Multicast-HOWTO는 (상대적으로 말해서) 옛날의 내용이며 그로 인해 부정확하거나 오해를 불러 일으킬 수 있습니다.

멀티캐스트 라우팅(multicast routing)을 할 수 있으려면, 자신이 원하는 멀티캐스트 라우팅 종류를 지원하도록 리눅스 커널을 구성해 주어야 합니다. 이를 위해선 어떤 종류의 멀티캐스트 라우팅을 사용하기를 바라는지 결정해야 합니다. 기본적으로 네 가지의 "일반적인" 종류들이 있습니다. WikiPedia:DVMRP(RIP유니캐스트 프로토콜의 멀티캐스트 버전), MOSPF(마찬가지, WikiPedia:OSPF의 경우), PIM-SM("WikiPedia:Protocol_Independent_Multicast - Sparse Mode", 멀티캐스트 그룹의 사용자들이 뭉쳐져 있지 않고 흩어져 있다고 가정함), 그리고 PIM-DM(마찬가지이지만 "Dense Mode", 즉 동일한 멀티캐스트 그룹 사용자들이 상당히 뭉쳐 있다고 가정함)이 그것입니다.

리눅스 커널에서는 이런 옵션들이 안 보인다는 걸 알 수 있을 것입니다. 이는, 프로토콜 자체는 Zebra나 mountd, pimd 같은 라우팅 응용 프로그램이 다루는 것이기 때문입니다. 하지만 그렇다고 해도, 커널 내에서 올바른 옵션을 선택하기 위해선 어떤 프로토콜을 사용할 것인지 잘 알고 있어야 합니다.

모든 멀티캐스트 라우팅에 대해서 "multicasting" 및 "multicast routing"을 (역자주: CONFIG_IP_MULTICASTCONFIG_IP_MROUTE) 활성화 시켜주어야 하는 건 분명합니다. DVMRP 및 MOSPF의 경우는 이걸로 충분합니다. PIM을 사용할 거라면, 접속하려는 네트워크가 PIM 프로토콜의 버전 1과 2중 어느 걸 사용하는가에 따라 PIMv1 또는 PIMv2를 활성화 시켜주어야 합니다.

선택을 마치고 새로운 리눅스 커널을 컴파일 하고 나면 이제 부팅 때 나열되는 IP 프로토콜에 WikiPedia:IGMP가 포함되어 있는 걸 볼 수 있을 것입니다. 이 프로토콜은 멀티캐스트 그룹을 관리하는 것입니다. 글을 작성하고 있는 현재 리눅스는 IGMP 버전 1과 2만을 지원합니다. 버전 3도 존재하며 문서화도 되어 있기는 합니다. 하지만 이건 실제로는 별 상관이 없는데, IGMPv3는 아직 새로운 것이어서 !IGMPv3의 추가적인 기능들은 별로 쓰이지 않을 것이기 때문입니다. IGMP는 그룹을 다루기에, 전체 그룹에서 가장 단순한 버전의 IGMP에 있는 기능들만 쓰이게 됩니다. 아직 !IGMPv1을 마주치기도 하지만, 대부분의 경우 IGMPv2가 쓰이게 될 것입니다.

지금까지는 그럭저럭 좋습니다. 우리는 멀티캐스팅을 활성화 시켰습니다. 이제 우리는 리눅스 커널에게 실제로 뭔가를 하도록 해서, 라우팅을 시작할 수 있어야 합니다. 이는 라우터 테이블에 멀티캐스트 가상 네트워크를 추가해 주는 걸 뜻합니다:
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 주소를 가지고 있지 않다는 걸 알 수 있을 것입니다. 놀랍군요! :) 이 주소는 그룹 주소(가입자들에 대한 "방송(broadcast)")이며, 그 그룹의 모든 구성원들은 그룹 주소가 아닌 자신의 주소로 응답하게 됩니다.
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 바이트에 기반해서 사상이 일어납니다:
   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        <요청과 동일> (대부분)


txqueuelen
이 큐의 길이는, ifconfigip로 보고 바꿀 수 있는, 인터페이스 설정에서 가져옵니다. 큐 길이를 10으로 설정하려면 이렇게 실행하십시오: ifconfig eth0 txqueuelen 10

tc로는 이 매개변수를 바꿀 수 없습니다!

9.2.2. Token Bucket Filter

토큰 버킷 필터(TBF)는 간단한 큐구조로서, 설정된 전송률을 초과하는 패킷을 보내지 않도록 하는 큐구조입니다. 그러나, 순간적으로 이 전송률를 초과하는 짧은 버스트(패킷이 빨리 연속되는 경우)의 경우에는 패킷을 전달합니다.

TBF는 매우 정밀하며, 네트웍과 프로세서에 많이 사용됩니다. 만약 여러분이 인터페이스의 속도를 느리게 낮추고자 한다면, 이 큐구조를 먼저 선택할 수 있습니다.

TBF의 구현은 버퍼(버킷, bucket- token(토큰)이라고 불리우는 가상적인 조각들에 의해 채워지는 바구니)와 정해진 토큰 발생률(token rate)로 구성됩니다. 버킷의 가장 중요한 파라메터는 그것의 크기이며, 토큰을 담을 수 있는 개수로 표시할 수 있습니다.

토큰이 쌓이면서 패킷이 도착 하기를 기다리고, 이것은 곧 버킷으로부터 지워집니다. 토큰과 데이터의 두 흐름을 연계하면, 다음과 같은 세가지 시나리오를 생각해 볼 수 있습니다.

  • 데이터가 TBF에 도착하는 속도가 토큰 발생률과 같은 경우, 각각 도착하는 패킷은 토큰과 일치하여 지연없이 바로 큐로 통과됩니다.
  • 데이터가 TBF에 도착하는 속도가 토큰 발생률보다 적은 경우, 패킷이 도착하는 것보다 토큰이 더 많이 생성되므로, 토큰은 버킷크기 만큼 쌓이게 되고, 그후에는 데이터가 도착하는 것보다 더 빨리 만들어지는 토큰은 지워질 것입니다. 버킷에 쌓인 토큰은 데이터가 연속으로 빨리 도착하는 버스트의 경우에 사용될 것입니다.
  • 데이터가 TBF에 도착하는 속도가 토큰 발생률보다 큰 경우, 이 경우 버킷에 쌓였던 토큰이 당분간 사용될 것입니다. 이것을 과제한 상태(overlimit situation)이라고 합니다. 만약 계속 패킷이 빠르게 도착한다면, 패킷 손실이 시작됩니다.

마지막 시나리오는 매우 중요합니다. 왜냐하면, 데이터를 통과시키는 필터로, 운영자가 대역폭을 조절할 수 있게 해주기 때문입니다.

토큰이 버킷에 쌓이는 것은 순간적으로 빠르게 데이터가 도착할 경우의 손실을 피하기 위해서 필요합니다. 그러나, 계속적인 부하는 패킷 지연을 야기할 것이고, 곧 손실될 것입니다.

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장에서 설명하는 몇가지 큐잉 규칙에 대해서 이야기 할것이다.

  • 순수히 외부로 가나는 통행량을 줄이려면 토큰 버킷 필터(TBF)를 쓰라. 버킷을 조절하면 매우 큰 대역폭에서도 잘 작동한다.

  • 연결이 정말 꽉차있고 어느 누구도 외부로 나가는 대역폭을 독점하게 하고 싶지 않다면 공평한 통계적 큐잉(SFQ)을 사용하라.

  • 매우큰 백본을 가지고 있고 무엇을 하고 있는지 알고 있다면 Random Early Drop(RED)를 고려해보라 (고급내용이 있는 장을 보라)

  • 외부에서 들어오는 통행량중 전달하지 않을 것을 '조절' 할때는 Ingress Policer를 사용하라. 들어오는 통행량 조절은 'policing' 이라 부르고, 여하튼, 'shaping'은 아니다.

  • 그것을 전달*중* 이라면, 자료를 전달하는 인터페이스에 TBF를 사용하라. 만일 조절하려는 통행량이 여러 인터페이스를 통해 나가서 조절할 필요가 없다면 그 경우 공통 요소는 들어오는 인터페이스 밖에 없다. 그 경우 Ingress Policer를 사용하라.

  • 통행량을 조절할 필요가 없는대신 인터페이스에 부하가 걸리는 것만 알아보고자 할경우 pfifo 큐 (pfifo_fast 가 아니고)를 사용하라. 내부 대역은 부족하지만 큐의 잔량 크기는 잴수 있다.

  • 마지막으로 - "사회적 조절"을 할수 있다. 원하는 것을 얻기 위해 항상 기술을 사용해야만 하는 것은 아니다. 사용자들은 기술적 속박을 불쾌하게 받아들인다. 몇마디 친절한 말이 정확하게 나뉜 대역폭보다 더 도움이 될수 있다.

9.4. Terminology


9.5. Classful Queuing Disciplines


9.5.1. Flows within classful qdiscs & classes


9.5.2. The qdisc family: roots, handles, siblings and parents


9.5.3. The PRIO qdisc


9.5.4. The famous CBQ qdisc


9.5.5. Hierarchical Token Bucket


9.6. Classifying packets with filters


9.6.1. Some simple filtering examples


9.6.2. All the filtering commands you will normally need


9.7. The Intermediate Queuing Device (IMQ)


9.7.1. Simple configuration


10. Load sharing over multiple interfaces


10.1. Caveats


10.2. Other possibilities


11. Netfilter & iproute - marking packets


12. Advanced filters for (re-)classifying packets


12.1. The u32 classifier


12.1.1. U32 selector


12.1.2. General selectors


12.1.3. Specific selectors


12.2. The route classifier


12.3. Policing filters


12.3.1. Ways to police


12.3.2. Overlimit actions


12.3.3. Examples


12.4. Hashing filters for very fast massive filtering


12.5. Filtering IPv6 traffic


12.5.1. How come that IPv6 tc filters do not work?


12.5.2. Marking IPv6 packets using ip6tables


12.5.3. Using the u32 selector to match IPv6 packet


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_martians
FIXME: conf/{default,all}/* 파일들을 설정하면 충분하지 않나요? - martijn
(역자주: 충분하지 않습니다. conf/all/* 파일은 동작에 영향을 주지 않으며, 인터페이스별 디렉터리 내의 파일을 직접 조작해 주어야 합니다.)

13.2. 숨겨진 설정들

자, 변경할 수 있는 매개변수들이 참 많이 있습니다. 모두를 나열해 볼 것입니다. 이는 Documentation/ip-sysctl.txt에(역자주: Documentation/networking/ip-sysctl.txt가 정확한 경로입니다.) (일부) 문서화 되어 있습니다.

이 설정들 중 몇몇은 커널을 컴파일 할 때 '호스트 대신 라우터로 구성하기'(역자주: NETFILTER, IP_ADVANCED_ROUTER 등)에 'Yes'로 대답했는가에 따라서 다른 기본값을 가집니다.

Oskar Andreasson 역시도 이 플래그들 전부에 대한 페이지를 가지고 있으며 우리 것보다 더 나은 것 같으니, [http]http://ipsysctl-tutorial.frozentux.net/도 확인해 보십시오.

13.2.1. ipv4 일반

일반적으로 주의할 것은 대부분의 속도 제한 기능이 루프백에서는 동작하지 않는다는 것입니다. 그러니 로컬에서 테스트 하지 마십시오. 제한은 'jiffy' 단위이며 앞서 언급한 토큰 버킷 필터를 사용해 적용됩니다.

커널은 초당 'HZ' 번(혹는 HZ 'jiffies' 만큼) 똑딱이는 내부 시계를 가지고 있습니다. Intel의 경우 'HZ'는 대부분 100입니다. 따라서 *_rate 파일을 50으로 설정하면 초당 2개 패킷을 허용하게 됩니다. 토큰 버킷 필터는 충분한 토큰을 모은 경우 최대 6개 패킷까지 집중되는 걸 허용합니다.

다음 목록의 몇몇 항목은 Alexey Kuznetsov <Mkuznet@ms2.inr.ac.ru> 및 Andi Kleen <Mak@muc.de>가 작성한 /usr/src/linux/Documentation/networking/ip-sysctl.txt에서 복사했습니다.

/proc/sys/net/ipv4/icmp_destunreach_rate
커널이 패킷을 전달할 수 없다고 판단하면 이를 제거하고, 패킷의 출발지로 그렇게 한 것에 대한 ICMP 알림을 보내 줍니다.

/proc/sys/net/ipv4/icmp_echo_ignore_all
echo 패킷에 대해 아무 대응도 하지 않습니다. 이걸 기본으로 설정하지 않는 게 가급적 좋지만, 호스트가 DoS 공격에서 중계점으로 쓰이고 있다면 이게 유용할 수 있습니다.

/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts [유용함]
네트워크의 브로드캐스트 주소로 ping을 하면 모든 호스트들이 응답하도록 되어 있습니다. 이건 세련된 서비스 거부 공격 도구에 쓰일 수 있습니다. 이걸 1로 설정하면 그런 브로드캐스트 메시지를 무시합니다.

/proc/sys/net/ipv4/icmp_echoreply_rate
어떤 한 목적지로 echo 응답을 보내는 속도입니다.

/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
이걸 설정하면 네트워크 내의 호스트가 어떤 프레임을 브로드캐스트 주소로 보낸 것으로 인식하여 잘못 대응하며 보낸 ICMP 오류를 무시합니다.

/proc/sys/net/ipv4/icmp_paramprob_rate
깨진 IP 혹은 TCP 헤더를 가진 잘못된 패킷에 대한 응답으로 보내는 비교적 알려지지 않은 ICMP 메시지입니다. 이 파일로 그러한 메시지를 보내는 속도를 제어할 수 있습니다.

/proc/sys/net/ipv4/icmp_timeexceed_rate
이건 traceroute에서 'Solaris middle star'(역자주: traceroute에서 응답하지 않아서 "*"로 표시되는 것)의 유명한 원인입니다. 보내는 ICMP Time Exceeded 메시지의 속도를 제한합니다.

/proc/sys/net/ipv4/igmp_max_memberships
호스트 상의 리스닝 하는 igmp (멀티캐스트) 소켓의 최대 개수입니다. FIXME: 정말인가요?

/proc/sys/net/ipv4/inet_peer_gc_maxtime
FIXME: inet peer 저장에 대해 좀더 설명을 추가해 주세요. 쓰레기 수집 작업 사이의 최대 간격입니다. 이 간격은 풀 상의 메모리가 줄어드는(혹은 소진되는) 것에 영향을 받습니다. jiffies 단위입니다.

/proc/sys/net/ipv4/inet_peer_gc_mintime
쓰레기 수집 작업 사이의 최소 간격입니다. 이 간격은 풀 상의 메모리가 많아지는 것에 영향을 받습니다. jiffies 단위입니다.

/proc/sys/net/ipv4/inet_peer_maxttl
항목의 최대 유지 시간입니다. 풀에 메모리가 없으면 (즉 풀 내의 항목의 개수가 아주 적으면) 이 시간이 지난 후 사용하지 않은 항목이 없어지게 됩니다. jiffies 단위입니다.

/proc/sys/net/ipv4/inet_peer_minttl
항목의 최소 유지 시간입니다. 재조립하는 쪽에서의 단편 유지 시간만큼은 되어야 합니다. 풀 크기가 inet_peer_threshold보다 작으면 이 최소 유지 시간이 보장됩니다. jiffies 단위입니다.

/proc/sys/net/ipv4/inet_peer_threshold
INET peer 저장소의 대략적인 크기입니다. 이 문턱값을 넘어가면서부터 항목들을 적극적으로 버리게 됩니다. 이 문턱값은 항목들의 유지 시간과 쓰레기 수집 작업 사이의 간격을 결정하기도 합니다. 항목이 많으면 유지 시간이 짧아지고 쓰레기 수집 간격도 짧아집니다.

/proc/sys/net/ipv4/ip_autoconfig
호스트가 RARP, BOOTP, DHCP, 기타 유사한 방법으로 IP 구성을 받아온 경우 이 파일에 1이 들어갑니다. 그렇지 않으면 0입니다.

/proc/sys/net/ipv4/ip_default_ttl
패킷의 유지 시간(Time To Live)입니다. 안전하게 64로 설정하십시오. 거대한 네트워크를 가지고 있다면 올려 주십시오. 재미로 올리지는 마십시오. 그러면 라우팅 루프가 더 큰 손상을 유발합니다. 몇몇 환경에서는 이 값을 낮추는 것을 고려해야 할 수도 있습니다.

/proc/sys/net/ipv4/ip_dynaddr
동적 인터페이스 주소로 dial-on-demand(역자주: 트래픽이 있을 때 연결을 하는 회선)를 사용한다면 이걸 설정해 주어야 합니다. demand 인터페이스가 올라오면 응답을 받지 못한 모든 로컬의 TCP 소켓을 올바른 주소로 다시 연결시켜 줍니다. 이는 인터페이스를 올려주는 연결 자체는 동작하지 않고 두 번째 시도부터 동작하는 문제를 해결해 줍니다.

/proc/sys/net/ipv4/ip_forward
커널이 패킷 전달을 하게 되는 경우입니다. 기본적으로 꺼져 있습니다.

/proc/sys/net/ipv4/ip_local_port_range
나가는 연결의 로컬 포트의 범위입니다. 기본적으로는 상당히 작은 1024부터 4999로 되어 있습니다.

/proc/sys/net/ipv4/ip_no_pmtu_disc
경로 MTU 발견(Path MTU discovery)을 비활성화 시키려면 이걸 설정해 주십시오. 경로 MTU 발견은 경로 상에서 가능한 최대의 MTU(Maximum Transfer Unit) 값을 알아내는 기법입니다. 친절 설명서장의 MTU 경로 발견에 대한 절을 참고하실 수 있습니다.

/proc/sys/net/ipv4/ipfrag_high_thresh
IP 조각 재조립에 쓰이는 최대 메모리입니다. ipfrag_high_thresh바이트의 메모리가 이 목적으로 할당되어 있으면 조각 처리부는 ipfrag_low_thresh에 도달할 때까지는 패킷을 쓰레기통에 던져넣게 됩니다.

/proc/sys/net/ipv4/ip_nonlocal_bind
응용 프로그램이 시스템 상의 장치에 없는 주소로 바인딩 할 수 있도록 해주고 싶으면 이걸 설정해 주십시오. 이는 장비가 비영속적인(혹은 동적) 연결상에 있을 때 유용합니다. 연결이 끊어져 있을 때도 서비스 프로그램이 시작하여 특정 주소로 바인딩을 할 수 있습니다.

/proc/sys/net/ipv4/ipfrag_low_thresh
IP 조각 재조립에 쓰이는 최소 메모리입니다.

/proc/sys/net/ipv4/ipfrag_time
IP 조각을 메모리에서 유지하는 초 단위 시간입니다.

/proc/sys/net/ipv4/tcp_abort_on_overflow
들어오는 연결이 많을 때의 동작을 제어하는 불리언 플래그입니다. 활성화 시키면 서비스에 과부하가 걸릴 때 커널이 재빠르게 RST 패킷을 보내도록 합니다.

/proc/sys/net/ipv4/tcp_fin_timeout
우리쪽에서 닫은 경우 소켓을 FIN-WAIT-2 상태에 두는 시간입니다. 상대에게 문제가 생겨서 그쪽을 닫아주지 않을 수도 있고 상대가 갑자기 죽어버릴 수도 있기 때문입니다. 기본값은 60초입니다. 2.2에서 썼던 일반적인 값은 180초였고, 그 값으로 돌아갈 수도 있습니다. 단, 부하가 적은 웹 서버에서조차도 왕창 남아있는 죽은 소켓들이 메모리 부족을 일으킬 위험이 있다는 걸 잊지 마십시오. FIN-WAIT-2 소켓은 최대 1.5K의 메모리만을 잡아먹기에 FIN-WAIT-1보다는 덜 위험하지만, 대신 더 오래 유지되는 경우가 많습니다. 참고: tcp_max_orphans.

/proc/sys/net/ipv4/tcp_keepalive_time
연결유지(keepalive)가 켜졌을 때 TCP가 얼마나 자주 연결유지 메시지를 보내는가입니다. 기본값: 2시간.

/proc/sys/net/ipv4/tcp_keepalive_intvl
조사용 패킷에 대한 응답이 없을 때 패킷을 얼마나 자주 재전송 하는가입니다. 기본값: 75초.

/proc/sys/net/ipv4/tcp_keepalive_probes
연결이 깨졌다고 판단할 때까지 TCP가 얼마나 많은 연결유지 조사 패킷을 보내는가입니다. 기본값: 9. tcp_keepalive_intvl과 곱하면 연결유지 패킷을 보내고서 연결이 응답 없이 유지될 수 있는 시간이 됩니다.

/proc/sys/net/ipv4/tcp_max_orphans
사용자 파일 핸들에 연결되어 있지 않아서 시스템이 가지고 있는 TCP 소켓의 최대 개수입니다. 이 개수를 초과하면 고아(orphaned) 연결은 즉시 초기화 되고 경고가 출력됩니다. 이 제한은 단순한 DoS 공격을 막기 위해서 존재할 뿐이며, 여기에 의존하거나 제한값을 억지로 낮춰선 안됩니다. 네트워크 상황이 기본값 이상을 필요로 한다면 도리어 (아마도 메모리 설치를 늘인 다음에) 이 값을 높여주어야 합니다. 그리고 네트워크 서비스가 시간을 끌도록(linger) 조정해 주고 그러한 상태를 좀더 공격적으로 죽여 주어야 합니다. 다시 한번 말하겠습니다: 각각의 고아 연결은 스왑 불가능한 메모리 64K를 잡아먹습니다.

/proc/sys/net/ipv4/tcp_orphan_retries
우리쪽에서 닫은 TCP 연결을 죽이기 전까지 몇 번이나 재시도를 할 것인가입니다. 기본값 7은 RTO에 때라서 50초-16분에 대응하게 됩니다. 그러한 소켓은 상당한 자원을 소모하므로, 장비가 부하가 있는 웹 서버라면 이 값을 낮추는 걸 생각해 봐야 합니다. 참고: tcp_max_orphans.

/proc/sys/net/ipv4/tcp_max_syn_backlog
연결해온 클라이언트의 응답(acknowldege)을 아직 받지 않은 연결 요청들 중 기억해 둘 개수의 최대값입니다. 기본값은 128Mb를 넘는 메모리를 가진 시스템에서는 1024이고, 그보다 작은 메모리의 장비에서는 128입니다. 서버가 과부하를 겪고 있다면 이 숫자를 늘여보십시오. 주의사항! 1024보다 크게 하려는 경우는 include/net/tcp.h에서 TCP_SYNQ_HSIZE를 TCP_SYNQ_HSIZE*16<=tcp_max_syn_backlog 관계가 유지되도록 바꿔주고서 커널을 다시 컴파일 하는 것이 좋습니다.

/proc/sys/net/ipv4/tcp_max_tw_buckets
시스템이 동시에 가지고 있은 timewait 소켓의 최대 개수입니다. 이 값을 초과하면 time-wait 소켓을 즉시 파괴하고 경고를 출력합니다. 이 제한은 단순한 DoS 공격을 막기 위해서 존재할 뿐이며, 제한값을 억지로 낮춰선 안됩니다. 네트워크 상황이 기본값 이상을 필요로 한다면 도리어 (아마도 메모리 설치를 늘인 다음에) 이 값을 높여주어야 합니다.

/proc/sys/net/ipv4/tcp_retrans_collapse
몇몇 구린 프린터와의 호환성을 위한 버그에 대한 버그입니다. 재전송시에 더 큰 패킷을 보내려고 함으로써 특정 TCP 스택의 버그를 피해갑니다.

/proc/sys/net/ipv4/tcp_retries1
뭔가 문제가 있으며 이를 네트워크 계층에 보고해야 한다는 판단을 내리기 전까지 몇 번이나 재시도를 할 것인가입니다. 최소의 RFC값은 3이며, 기본값이기도 합니다. 이는 RTO에 따라서 3초-8분에 대응합니다.

/proc/sys/net/ipv4/tcp_retries2
살아있는 TCP 연결을 죽이기 전까지 몇 번이나 재시도를 할 것인가입니다. [http]RFC 1122에서는 제한값이 100초보다 길어야 한다고 얘기하고 있습니다. 그건 너무 작은 값입니다. 기본값 15는 RTO에 따라서 13-30분에 대응합니다.

/proc/sys/net/ipv4/tcp_rfc1337
이 불리언값은 RFC 1337에서 설명한 'tcp에서의 time-wait 암살 위험'에 대한 수정 사항을 활성화합니다. 활성화하면 커널은 time-wait 상태인 소켓에 대해 RST 패킷을 무시합니다. 기본값: 0

/proc/sys/net/ipv4/tcp_sack
Selective ACK를 사용합니다. 이는 특정 패킷이 빠졌다는 걸 알려주도록 하며 빠른 복구를 도와줍니다.

/proc/sys/net/ipv4/tcp_stdurg
TCP urg 포인터 필드에 대한 호스트 요구사항에 따른 해석을 적용합니다. 대부분의 호스트는 이전의 BSD식 해석을 적용하기에, 이걸 켜주면 리눅스가 그 호스트들과 제대로 통신하지 못할 수도 있습니다. 기본값: FALSE

/proc/sys/net/ipv4/tcp_syn_retries
새 연결을 포기할 때까지 커널이 SYN 패킷을 보내 보는 횟수입니다.

/proc/sys/net/ipv4/tcp_synack_retries
연결의 반대편을 열어주기 위해 커널은 앞서 받은 SYN에 응답하는 ACK를 얹어서 SYN를 보냅니다. 이게 삼단계 핸드셰이킹의 2부입니다. 이 설정은 연결을 포기할 때까지 커널이 SYN+ACK 패킷을 보내 보는 횟수입니다.

/proc/sys/net/ipv4/tcp_timestamps
timestamp는 여러 가지 목적이 있지만, 일련 번호를 되돌리는 것(wrapping)에 대한 보호를 위해 쓰입니다. 1 기가비트 연결에서는 이전 생성열의 것이라서 진로를 벗어난 값을 가진 이전의 일련 번호를 다시 마주칠 수 있습니다. timestamp는 이를 '오래된 패킷'이라고 알 수 있게 해줍니다.

/proc/sys/net/ipv4/tcp_tw_recycle
TIME-WAIT 소켓의 빠른 재사용을 활성화합니다. 기본값은 1입니다. 기술 전문가의 조언/요청 없이 값을 바꿔선 안됩니다.

/proc/sys/net/ipv4/tcp_window_scaling
TCP/IP는 보통 65535 바이트까지 윈도우가 커질 수 있도록 해줍니다. 정말 빠른 망에서는 이게 충분치 않을 수 있습니다. 윈도우 스케일링 옵션은 거의 기가바이트의 윈도우를 허용하는데, 이는 높은 대역폭과 지연 시간을 가진 제품에 좋습니다.

13.2.2. 장치별 설정

DEV는 실제 인터페이스, 또는 'all(전체)'이나 'default(기본값)'을 나타냅니다. 기본값은 또한 생성될 인터페이스에 대한 설정을 바꿔줍니다.

/proc/sys/net/ipv4/conf/DEV/accept_redirects
당신이 라우터를 잘못 사용하고 있다고 (즉, 당신의 패킷을 동일한 일터페이스에서 재전송 해주어야 한다고) 판단하면 라우터는 ICMP Redirect를 보내줍니다. 하지만 이건 미묘한 보안 위험이 될 수 있기에, 이걸 끄고서 안전한 전환(redirect)을 사용하는 걸 원할 겁니다.

/proc/sys/net/ipv4/conf/DEV/accept_source_route
이제는 별로 쓰이지 않습니다. 이전에는 패킷이 가면서 방문할 IP 주소 목록을 알려줄 수 있었습니다. 리눅스 장비가 이 IP 옵션을 존중하도록 해줄 수 있습니다.

/proc/sys/net/ipv4/conf/DEV/bootp_relay
출발지 주소가 0.b.c.d이고 목적지가 이 호스트가 아닌 패킷을 자신에게 온 패킷으로 받아들입니다. BOOTP 전달 데몬이 이 패킷을 잡아채서 전달하게 됩니다.

/proc/sys/net/ipv4/conf/DEV/forwarding
이 인터페이스에서 IP 포워딩을 켜거나 끕니다.

/proc/sys/net/ipv4/conf/DEV/log_martians
역경로 필터링에 대한 절을 참고하십시오.

/proc/sys/net/ipv4/conf/DEV/mc_forwarding
이 인터페이스에서 멀티캐스트 전달을 할 것인지입니다.

/proc/sys/net/ipv4/conf/DEV/proxy_arp
이걸 1로 설정하면 그 주소에 대한 라우트를 커널이 가지고 있는 경우 이 인터페이스가 ARP 요청에 응답하게 됩니다. 'ip pseudo 브리지'를 구축하는 데에 아주 유용하게 사용할 수 있습니다. 이걸 켜주기 전에 넷마스크가 확실히 올바른지를 신경써 주십시오! 또한 따로 언급하는 arp_filter 역시도 ARP 질의에 영향을 준다는 걸 알아두십시오!

/proc/sys/net/ipv4/conf/DEV/rp_filter
역경로 필터링에 대한 절을 참고하십시오.

/proc/sys/net/ipv4/conf/DEV/secure_redirects
기본 게이트웨이 목록에 있는 게이트웨이에 대해서만 ICMP 전환(redirect) 메시지를 받아들입니다. 기본적으로 켜져 있습니다.

/proc/sys/net/ipv4/conf/DEV/send_redirects
앞서 언급한 전환 메시지를 보내 주는지입니다.

/proc/sys/net/ipv4/conf/DEV/shared_media
이걸 설정해 주지 않으면 커널은 이 장치상에서 서로 다른 서브넷들이 직접 통신할 수 있다고 가정하지 않습니다. 기본 설정은 'yes'입니다.

/proc/sys/net/ipv4/conf/DEV/tag
FIXME: 채워주세요.

13.2.3. 이웃(neighbor) 정책

DEV는 실제 인터페이스, 또는 'all(전체)'이나 'default(기본값)'을 나타냅니다. 기본값은 또한 생성될 인터페이스에 대한 설정을 바꿔줍니다.

/proc/sys/net/ipv4/neigh/DEV/anycast_delay
neighbor solicitation 메시지에 대한 응답의 임의 지연의 최대값이며 jiffies(1/100초) 단위입니다. 아직 구현되어 있지 않습니다 (리눅스는 아직 애니캐스트 지원을 하지 않습니다).

/proc/sys/net/ipv4/neigh/DEV/app_solicit
사용자 수준 ARP 데몬에게 보내는 요청의 개수를 결정합니다. 0을 사용해 꺼주십시오.

/proc/sys/net/ipv4/neigh/DEV/base_reachable_time
RFC2461에서 명세한 대로 random reachable time값을 계산하는 데 쓰이는 기본값입니다.

/proc/sys/net/ipv4/neigh/DEV/delay_first_probe_time
이웃이 접근 가능한 경우 첫 번째 time probe에 대한 지연 시간입니다. (gc_stale_time 참고)

/proc/sys/net/ipv4/neigh/DEV/gc_stale_time
얼마나 자주 낡은 ARP 항목을 검사할 것인지를 결정합니다. ARP 항목이 낡은 것이 되면 그 항목을 다시 확인하게 됩니다 (이는 IP 주소가 다른 장비로 옮겨간 경우에 유용합니다). ucast_solicit이 0보다 크면 먼저 알려진 호스트에게 ARP 패킷을 직접 보내려고 시도합니다. 그게 실패하고 mcast_solicit이 0보다 크면 ARP 요청을 브로드캐스팅 합니다.

/proc/sys/net/ipv4/neigh/DEV/locktime
이전 항목이 최소한 locktime만큼 오래된 경우에만 ARP/이웃 항목을 새 항목으로 교체합니다. 이는 ARP 캐시 스래싱을 방지해 줍니다.

/proc/sys/net/ipv4/neigh/DEV/mcast_solicit
멀티캐스트 solicitation에 대한 최대 시도 횟수입니다.

/proc/sys/net/ipv4/neigh/DEV/proxy_delay
프럭시 ARP 항목을 가지고 있는 ARP 요청에 대해 응답하기까지의 최대 시간입니다 (실제 시간은 random0..proxy_delay입니다). 몇몇 경우에 네트워크 플러딩을 막는 데에 사용합니다.

/proc/sys/net/ipv4/neigh/DEV/proxy_qlen
지연된 프럭시 arp 타이머의 최대 큐 길이입니다. (proxy_delay 참고)

/proc/sys/net/ipv4/neigh/DEV/retrans_time
재전송되는 Neighbor Solicitation 메시지간의 시간이며, jiffies(1/100초) 단위입니다. 주소 알아내기 및 이웃이 접근 불가능한지를 알아내는 데에 쓰입니다.

/proc/sys/net/ipv4/neigh/DEV/ucast_solicit
유니캐스트 solicitation에 대한 최대 시도 횟수입니다.

/proc/sys/net/ipv4/neigh/DEV/unres_qlen
대기중인 arp 요청에 대한 최대 큐 길이입니다. 즉, ARP 주소를 아직 확인하고 있는 동안 다른 계층에서 받아들이는 패킷의 개수입니다.

13.2.4. 라우팅 설정

/proc/sys/net/ipv4/route/error_burst/proc/sys/net/ipv4/route/error_cost
이 매개변수들은 라우팅 코드가 커널 로그에 기록하는 경고 메시지를 제한하는 데에 쓰입니다. error_cost 인자가 높으면 더 적은 메시지를 기록하게 됩니다. error_burst는 언제 메시지가 사라질 것인지를 제어합니다. 기본 설정은 5초에 한번으로 경고 메시지를 제한합니다.

/proc/sys/net/ipv4/route/flush
이 파일에 기록을 하면 라우팅 캐시를 비워버립니다.

/proc/sys/net/ipv4/route/gc_elasticity
라우팅 캐시에 대한 쓰레기 수집 알고리즘의 빈도 및 동작을 제어하는 값입니다. 이건 장애 극복(fail over)을 하는 경우에 중요할 수 있습니다. 이전 라우트가 죽어서 새로운 라우트로 리눅스가 건너뛸 때까지 최소한 gc_timeout초만큼 지나게 됩니다. 기본값이 300으로 설정되어 있으며, 빠른 장애 극복을 위해 낮춰주는 것도 가능합니다. Ard van Breemen의 [http]이 글도 참고하십시오.

/proc/sys/net/ipv4/route/gc_interval
/proc/sys/net/ipv4/route_gc_elasticity를 참고하십시오.

/proc/sys/net/ipv4/route/gc_min_interval
/proc/sys/net/ipv4/route_gc_elasticity를 참고하십시오.

/proc/sys/net/ipv4/route/gc_thresh
/proc/sys/net/ipv4/route_gc_elasticity를 참고하십시오.

/proc/sys/net/ipv4/route/gc_timeout
/proc/sys/net/ipv4/route_gc_elasticity를 참고하십시오.

/proc/sys/net/ipv4/route/max_delay
라우팅 캐시를 비워내는 것에 대한 최대 지연 시간입니다.

/proc/sys/net/ipv4/route/max_size
라우팅 캐시의 최대 크기입니다. 캐시가 이 크기에 도달하면 오래된 항목들이 없어지게 됩니다.

/proc/sys/net/ipv4/route/min_adv_mss
FIXME: 채워주세요.

/proc/sys/net/ipv4/route/min_delay
라우팅 캐시를 비워내는 것에 대한 최소 지연 시간입니다.

/proc/sys/net/ipv4/route/min_pmtu
FIXME: 채워주세요.

/proc/sys/net/ipv4/route/mtu_expires
FIXME: 채워주세요.

/proc/sys/net/ipv4/route/redirect_load
특정 호스트로 더 많은 ICMP 전환 메시지를 보내야 하는가를 결정하는 인자입니다. 전환 메시지의 부하 한계(redirect_load) 또는 최대 개수(redirect_number)에 도달하고 나면 더이상 전환 메시지를 보내지 않게 됩니다.

/proc/sys/net/ipv4/route/redirect_number
/proc/sys/net/ipv4/route/redirect_load를 참고하십시오.

/proc/sys/net/ipv4/route/redirect_silence
전환 메시지에 대한 중지 시간입니다. 부하나 개수 제한에 도달하여 중지된 후라고 해도, 이 시간이 지나면 전환 메시지를 다시 보내게 됩니다.

14. 전문적이고 덜 사용되는 큐 구조들

앞에서 언급된 큐들 이외에, 리눅스 커널은 이 장에서 언급되는 특별한 큐들을 포함하고 있다.

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.2. Clark-Shenker-Zhang algorithm (CSZ)


14.3. DSMARK


14.3.1. Introduction


14.3.2. What is DSMARK related to?


14.3.3. Differentiated Services guidelines


14.3.4. Working with DSMARK


14.3.5. How SCH_DSMARK works


14.3.6. TC_INDEX Filter


14.4. Ingress qdisc


14.4.1. Parameters & usage


14.5. Random Early Detection (RED)


14.6. Generic Random Early Detection

GRED에 대해 많이 알려진 것이 없습니다. GRED는 Diffserv tcindex에 기반한 내부적인 큐를 가지고 있습니다.관련된 슬라이드는 [http]여기(링크깨짐)에 따르면, Dave Clark의 RIO처럼 시스코의 'Distributed Weighted RED'의 기능을 포함하고 있습니다. Drop 파라메터를 각 가상큐별로 설정할 수 있습니다.

FIXME: 추가적인 정보를 Jamal 또는 Werner에게 알려주세요.

(softgear- GRED에 대해서는 http://www.opalsoft.net/qos/DS.htm 에서 더 많은 정보를 얻을 수 있습니다)

14.7. VC/ATM emulation


14.8. Weighted Round Robin (WRR)

이 큐구조는 표준 리눅스 커널에는 포함되어 있지 않지만, [http]여기(링크깨짐)에서 다운 받을 수 있습니다. 현재 이 큐구조는 2.2커널에서 테스트 중이고, 2.4,2.5커널에서도 아마 동작할 것입니다. WRR큐 구조는 라운드 로빈 스킴(순서대로 돌아가면서 서비스해 주는 방식)을 사용하여 각 클래스별로 대역폭을 할당합니다. 이것은,CBQ처럼, 각 클래스에 또다른 큐구조를 집어 넣을 수 있습니다. 모든 클래스는 각각 가중치를 가지고 대역폭을 얻게 됩니다. 가중치는 tc프로그램을 이용하여 직접 설정할 수 있습니다. 그러나, 지나치게 많은 데이터가 있는 경우 가중치는 자동으로 내려갈 수 있습니다.

이 큐구조는 내장 분류자(classifier)를 가지고 있습니다. 이는 다른 클래스나 장비로부터 들어오는 패킷 또는 나가는 패킷에 할당할 수 있습니다. MAC 또는 IP 그리고 source 또는 destination주소를 사용할 수 있습니다. 그러나, MAC주소는 Linux box가 ethernet bridge로 동작할때만 사용할 수 있습니다. 클래스는 패킷에 표시된 장비의 주소에 따라 자동으로 할당됩니다. 이 큐구조는 많은 인터넷 연결이 공유되는 곳에서 유용하게 사용될 수 있습니다. WRR 배포판에는 이러한 곳에서 동작할 수 있는 스크립트들이 포함되어 있습니다.

15. Cookbook


15.1. Running multiple sites with different SLAs


15.2. Protecting your host from SYN floods


15.3. Rate limit ICMP to prevent dDoS


15.4. Prioritizing interactive traffic


15.5. Transparent web-caching using netfilter, iproute2, ipchains and squid


15.5.1. Traffic flow diagram after implementation


15.6. Circumventing Path MTU Discovery issues with per route MTU settings


15.6.1. Solution


15.7. Circumventing Path MTU Discovery issues with MSS Clamping (for ADSL, cable, PPPoE & PPtP users)


15.8. The Ultimate Traffic Conditioner: Low Latency, Fast Up & Downloads


15.8.1. Why it doesn't work well by default


15.8.2. The actual script (CBQ)


15.8.3. The actual script (HTB)


15.9. Rate limiting a single host or netmask


15.10. Example of a full nat solution with QoS


15.10.1. Let's begin optimizing that scarce bandwidth


15.10.2. Classifying packets


15.10.3. Improving our setup


15.10.4. Making all of the above start at boot


16. Building bridges, and pseudo-bridges with Proxy ARP


16.1. State of bridging and iptables


16.2. Bridging and shaping


16.3. Pseudo-bridges with Proxy-ARP


16.3.1. ARP & Proxy-ARP


16.3.2. Implementing it


17. Dynamic routing - OSPF and BGP


17.1. Setting up OSPF with Zebra


17.1.1. Prerequisites


17.1.2. Configuring Zebra


17.1.3. Running Zebra


17.2. Setting up BGP4 with Zebra


17.2.1. Network Map (Example)


17.2.2. Configuration (Example)


17.2.3. Checking Configuration


18. Other possibilities


19. Further reading


20. Acknowledgements



DeleteMe 오래 전에 lartc 번역을 하던 것이 있습니다. 번역의 시작을 kldp 쪽으로 미리 알리지 않고 개인적으로 하던 작업이어서 due 를 두지 않았더니 중단된 상태네요. 지금은 revision 얼마인지 모르겠지만 한 일 년 전의 문서를 기준으로 번역한 것이니 참고하세요. 아래 주소에 있습니다.

번역 작업을 그만둔 이유가.. 아무래도 원문의 맛 그대로를 한국어로 옮긴다는 것은 제 능력으로 무리였다는 점이 가장 크지 않았나 합니다. -- ai
음.. 마무리를 하셨으면 더 좋았을 텐데요.. 그래도 아예 없는 것 보다는 뒷 사람을 위해서라도 하는게 좋죠.. ^^ -- 너바나

허락도 없이 감히 끼어들었습니다.. 워낙에 번역(?) 해보고 싶던 문서라서요.. 양이 좀 많고 계속해서 업데이트 되고 있는 문서라 중간중간 짬짬이 끼어들게요.. 그리고 LARTC 홈페이지 링크했습니다.. ^^;;; -- scipione

괜찮습니다.. 시작은 ai 님이 먼저 하신거고 전 아직 옮기는 데도 시간이 부족해서 천천히 해 나갈 생각이니 진도가 안나가고 있구나 하고 생각되면 계속 껴들어 주세요.. ^^ -- 너바나 집에서는.. Anonymous 로..

개인적으로 QoS에 대해서 관심이 많아서 이 문서를 보다가 이곳까지 오게 되었습니다. 참.. 힘든작업 하십니다... 워낙 엄청난 자료들이라서.. 개인적으로나마 저도 docbook에 대해 공부를 하고 해석을 해나가 보겠습니다만... 도움이 될지는 미지수 입니다... -_-;; 그럼 수고들 하십시요.. -- SkullQ

ID
Password
Join
Don't be overly suspicious where it's not warranted.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2006-09-15 00:31:31
Processing time 0.0537 sec