(1) 개요: 마이크로소프트와 인텔은 윈도우시스템이 다른 시스템의 디스크나 프린터같은 자원을 공유할 수 있도록 Server Message Block(SMB)이라는 프로토콜을 개발하였는데, 삼바란 이 SMB를 이용하여 리눅스와 윈도우와의 자료 공유 및 하드웨어를 공유할 수 있도록 해준다. 현재 마이크로소프트에서는 SMB라는 이름보다는 좀 더 범위가 큰CIFS(Common Internet File System)라는 프로토콜로 부른다. 이 프로토콜은 SMB 프로토콜에 LanMana ger와NetBIOS 프로토콜까지 포함한다.
(2) 삼바의 기능
1) 리눅스파티션과 윈도우와의 공유
2) 윈도우파티션과 리눅스와의 공유
3) 리눅스의 프린터와 윈도우와의 공유
4) 윈도우의 프린터와 리눅스와의 공유
2. 삼바(SAMBA)의 설치
(1) rpm패키지로 설치하기
1) 설치의 확인
rpm -qi samba 나 rpm -qa |grep samba 명령등을 내려 삼바가 설치되어 있는지 확인한다.
11) 삼바를 실행하는 스크립트파일을 /etc/rc.d/init.d/디렉토리에 복사한다. 삼바소스 디렉토리에서packging/RedHat 디렉토리에 보면 삼바구동스크립트파일인 smb.init이 있는데 이 파일을 samba라는 이름으로 복사한다. 예) cp smb.init /etc/rc.d/init.d/samba
12) 데몬실행파일 PATH가 설정된 경로로 복사한다. 보통 소스로 설치하면 데몬을 실행하는 파일인 smbd와 nmbd가/usr/local/samba/sbin디렉토리에 있다. 이 경로는 현재 PATH설정이 안 되어있 으므로 PATH를 설정하거나/usr/sbin디렉토리에 복사한다. 예) cp smbd nmbd /usr/sbin
2. 삼바의 구성
(1) 데몬: 삼바를 이용하기 위해서는 두 개의 데몬이 필요하다.
1) 기본데몬
ㄱ. smbd: SMB데몬 - 파일과 프린터공유, 사용자의 권한부여 및 확인
ㄴ. nmbd: 클라이언트를 위해 NetBIOS nameserver를 지원하고 browsing(서비스통지)한다.
1) 개요: smb.conf는 삼바의 환경설정파일로 파일안의 구성은 win.ini와 비슷하다. 크게 Global Setting과 Share Denition으로 나누고 다시 각 내용은 [] 기호를 이용하여 섹션(Section) 으로 구분한다.
2) 역할: 삼바를 제어하는 환경파일이다. 이 파일에서 외부와 공유시킬 시스템 자원과 어떠한 제약을 할 것인지를 지정한다.
3) 위치: 보통 /etc디렉토리에 위치하나 배포판에 따라 /etc/samba디렉토리에 위치할 수도 있다.
4) 파일내부의 유형
ㄱ. #으로 시작하는 행: 이 행은 주석처리되어 무시된다.
ㄴ. ;으로 시작하는 행: 이 행들도 주석행으로 간주되어 무시된다. 보통 이런 행은 설정행이 작동하지 않도록 하는데 사용된다. ;대신에 #을 사용해도 된다. 이 두 가지 유형의 주석이 사용되는 이유는 #은 유닉스에서 사용하는 주석이고. ;는 윈도우에서 사용하는 주석이라 두 가지 모두 사용한다.
ㄷ. [ ]을 사용하는 행: 섹션을 정의한다. 하나의 섹션이 정의된 후 그 다음 섹션이 정의될 때까지의 행들은 해당 섹션에 속한다.
ㄹ. name = value 행: 사용하는 옵션과 해당값을 설정하는 행들이다.
5) 기본적인 섹션
ㄱ. [global]: 삼바서버의 전체적인 환경설정을 담당하는 섹션
ㄴ. [homes]: 사용자들이 자신의 홈디렉토리로 접근할 때의 권한을 설정하는 섹션
ㄷ. [printers]: 프린터관련 권한을 설정하는 섹션
(3) 실행파일
1) smbclient
ㄱ. 설명: 유닉스를 위한 삼바클라이언트 명령어로 윈도우의 서버로 접근하기 위해 사용한다.
ㄴ. 사용법
smbclient [option] [접속하고자할 호스트명]
ㄷ. option
-L: 접속하고자할 호스트명을 입력한다.
-U: 접속할 때의 사용자명을 입력한다.
ㄹ. 사용예
a. [root@www root]# smbclient -L system2 -U administrator
=> system2라는 호스트에 administrator라는 권한으로 접속한다.
b. [root@www root]# smbclient -L system2 -U administrator%1234
4) smbprint.sysv: smbprint와 같지만 System V계열 유닉스에서 사용한다.
5) smbstatus: 현재의 삼바 연결상태를 보여준다.
6) smbrun: 삼바 호스트의 응용프로그램 실행을 용이하게 하는 스크립트이다.
7) testparm
ㄱ. 설명: 삼바의 환경설정파일인 smb.conf파일의 설정이 제대로 되었는지 확인하는 명령이다.
ㄴ. 사용법 testparm [환경설정파일경로] [IP주소]
ㄷ. 사용예
a. [root@www root]# testparm => 현재 서버에서 /etc/smb/smb.conf파일의 설정을 확인한다.
b. [root@www root]# testparm /etc/smb/smb.conf 192.168.1.3 => 192.168.1.3의 IP주소를 갖는 삼바서버의 /etc/smb/smb.conf파일의 설정을 확인한다.
8) nmblookup
ㄱ. 설명: WINS 서버에 질의할 때 사용하는 명령이다. DNS서버에 질의하는 nslookup명령과 유사 하다.
ㄴ. 사용법
nmblookup option
ㄷ. option
-U: 서버이름을 지정한다. 보통 -R옵션과 같이 사용한다.
-R: 조회할 이름을 지정한다.
ㄹ. 사용예
a. [root@www root]# nmblookup samba.org -R 'IRIX#1B' => samba.org 라는 서버에 IRIX#1B라는 이름을 조회한다.
b. [root@www root]# nmblookup \* => 브로드캐스트 영역에 있는 모든 이름을 조회한다.
3. smb.conf를 이용한 세팅
(1) 전체설정(Global Setting)
1) workgroup = MYGROUP => 윈도우의 작업그룹처럼 공유그룹을 지정한다.
2) server string = Samba Server => 서버에 대한 설명을 부여해 준다.
3) hosts allow = 192.168.1. 192.168.2. 127. => 삼바 서버에 접속을 허용할 호스트를 지정하는데 사용한다. 접속할 허용할 호스트는 아이피 주소, 호스트명 등을 지정할 수 있으며, 네트워크/넷마스크형태로도 지정할 수 있다. 또한 EXCEPT라는 키워드와 와일드문자도 사용가능하다. 참고로 삼바서버에 접속이 불가능하게 하려면 hosts deny로 설정한다. 예) 1. hosts allow = 192.168.1. 192.168.2. 127. => 192.168.1.0 네트워크대역에 속한 모든 호스트들과 로컬시스템(127.0.0.0네트워크) 에서 접속이 가능하다.
2. hosts allow = 192.168.1. EXCEPT 192.168.1.220 192.168.1.244 => 192.168.1.220과 192.168.1.244를 제외한 192.168.1.0 네트워크에 속한 모든 호스트들이 삼바 서버에 접속할 수 있다.
3. hosts allow = 192.168.1.0/255.255.255.0 => 192.168.1.0 네트워크에 속한 모든 호스트들의 접속을 허용한다.
=> 서버에 의해 사용되는 printcap name을 겹쳐쓰기 하고자 할 때 그 위치를 지정한다.
5) load printers = yes
=> 삼바 서버의 printcap에 정의된 모든 프린터 목록이 자동적으로 로딩되게 할 것인가를 지정하는 옵션이다. 네트워크 프린터를 삼바서버에 연결하여 사용하고자 한다면 선택해야 한다.
6) printing = lprng
=> 프린터 시스템 종류를 지정하는 옵션 비표준 프린터시스템이 아니면 지정할 필요가 없다.
7) ; guest account = pcguest
=> 공유 설정 섹션에서도 사용하는 항목으로, guest ok로 명시되어 있는 서비스에 접근할 유저를 지정해 준다. 보통 클라이언트가 손님서비스(guest service)에 접속할 수 있게 된다. 이러 한 유저는 /etc/passwd파일안에 존재하는 계정이어야 하며, 보통 "nobody"로 설정하면 된다.
8) log file = /var/log/samba/%m.log => 삼바 서버에 접속하는 호스트의 접속 로그에 대한 기록을 저장하는 파일을 지정한다.
9) max log size = 0 => 로그 파일의 최대 크기를 KB단위로 제한두려고 할 때 사용되는 옵션이다. 제한을 두었을경 우에 이를 초과하게 되면 .old확장자를 가진 파일로 저장되고 새로운 파일이 생성된다. 현재처럼 0으로 설정하면 파일의 크기에 제한을 두지 않는다.
10) security = user
=> 보안관련 옵션으로 클라이언트가 삼바서버에 접속할 때 인증 레벨을 부여하는 옵션이다.
보안모드에는 4가지모드가 있는데 user, share, server, domain등이다. \
* 4가지 모드 user: 삼바 서버에 접속하는 클라이언트는 먼저 반드시 윈도우 시작시 사용자명과 패스워드로 로그인을 한 후에 삼바 서버에 접속할 때 같은 사용자명으로 패스워드를 확인한 후에 접속이 이루어진다.
share: 유효한 사용자명과 패스워드로 삼바 서버에 로그인을 하지 않아도 서버에 접속할 수있게 하므로, 삼바 서버 인증과정을 필요로 하지 않을 때 이 레벨로 지정하면 된다. 공유 디렉토리 접근에 제한을 두는 경우에 사용할 수 있다.
server: 윈도우 NT와 같은 다른 삼바 서버가 존재해야 하며, 다른 삼바 서버에 사용자명과 패스 워드를 전달하여 올바른지를 확인한다.
domain: 윈도우 NT서버가 있어야 가능하며, 삼바서버가 사용자명과 패스워드를 윈도우NT의 도메인 컨트롤러(Domain Controller)에 전달하여 유효한지 확인하는 방법이다.
11) ; password server = <NT-Server-Name>
=> 보안옵션에서 server나 domain값을 설정했을 경우에 윈도우 NT같은 다른 삼바서버의NetBIOS이름으로 지정한다.
12) ; password level = 8 ; username level = 8 => 패스워드 레벨과 유저 레벨을 설정하는 것으로 8개 문자를 사용하도록 설정한다.
13) encrypt passwords = yes => 삼바서버에 클라이언트의 접속이 이뤄지는 과정에서 인증을 위하여 암호화 패스워드 옵션을 사용할 수 있다. 암호화된 패스워드를 지정하는 옵션이다.
14) smb passwd file = /etc/samba/smbpasswd => 이 옵션은 encrypt passwords항목과 같이 사용되는 것으로 암호화된 삼바 사용자의 아이디 와 패스워드가 기록되는 파일이다. 이 파일에 패스워드를 추가하는 명령은 smbpasswd이다.
=> 삼바에 연결된 네트워크 인터페이스를 설정하는 것으로, 인터페이스는 IP/netmask조합으로 지정할 수 있다. 즉, 위의 설명은 삼바서버가 서로 네트워크 인터페이스를 사용할 때 사용하는 것으로 192.168.12.2 호스트와 192.168.2.2 호스트에 연결을 허용한다는 의미이다.
=> 이 옵션은 삼바가 nmbd에 의해 서브넷상에서 로컬마스터브라우저가 될 수 있도록 허용하는 것으로 no라고 설정하면 nmbd데몬은 서브넷상에서 로컬 마스터브라우저가 되지 않는다.
22) ; os level = 33
=> 삼바서버가 브라우저 선거에 있어서 자신을 알릴 수 있는 레벨을 설정하는 것으로 이 값에 의해서 nmbd데몬이 로컬브로드캐스트지역에서 WORKGROUP에 대해 로컬마스터 브라우저가 될 수 있는지 결정된다. 이 값을 0으로 설정하면, nmbd데몬은 윈도우 머신에 대해서 선거권을 상실하므로 로컬마스터 브라우저가 되질 못한다. (관련문서는 BROWSING.txt)|
23) ; domain master = yes
=> 이 옵션은 삼바가 도메인 마스터 브라우저가 되도록 해준다. 이것은 삼바와 서브넷간의 브라우저 리스트를 모집할 수 있게 해준다. 만일 NT도메인 컨트롤러를 가지고 있다면 이 기능을 사용해서는 안된 다.
24) ; preferred master = yes| => 삼바구동시 로컬 마스터 선거를 강요하여 선거에서 이길 수 있게 보다 많은 가능성을 부여해 주는 옵션이다. 이 옵션은 domain master = yes옵션과 같이 사용하여 nmbd데몬에 의해 도메인 마스터가 될 수 있도록 해준다.
=> 삼바서버가 WORKGROUP에 윈도우98 도메인 로그온 역할을 할 것인지의 여부를 지정한다.
27) ; logon script = %m.bat
; logon script = %U.bat
=> 사용자가 성공적으로 로그인을 하였을 때 다운로드하여 작동할 수 있도록 배치파일(*.bat) 또는 NT명령파일(.cmd)을 지시해 주는 옵션이다. 배치파일은 마지막 줄에 cr/if가 들어있어야 하므로 도스편집기에서 만드는 것을 권장한다. 내용은 사용자가 임의대로 지정할 수 있다.
예) 보통 모든 클라이언트 머신들이 서버와 똑같은 시간에 시간을 맞추도록 할 수 있다. NET TIME \\SERVER /SET /YES
28) ; logon path = \\%L\Profiles\%U
=> 윈도우98 및 NT에서 user.dat과 같은 로우밍 프로파일(roaming profile)을 어디에 지정할 것인가를 지정해 주는 옵션이다. %L은 서버의 NetBIOS이름으로 대치되고, %U는 사용자 이름으로 대치된다. 이 옵션을 사용할 때[Profile]공유 항목에서 주석을 풀어 주어야 한다.
29) ; wins support = yes
=> 삼바서버에서 nmbd데몬이 wins서버의 역할을 할 수 있는지 여부를 지정한다. 만일 이 옵션을 선택하기 위해서는 반드시 다중 서브넷 네트워크를 가지고 있어야 하며, wins서버로 될특정 nmbd데몬이 있어야 한다.
(참고) WINS(Windows Internet Naming Service)
마이크로소프트 윈도우NT 서버의 일부인 WINS는 각 구성 변경에 수반되는 사용자 또는 관리자가 없는 IP주소들과 컴퓨터 이름 및 위치들과의 결합을 관리한다. WINS는 컴퓨터 이름과 IP주소를 서로 매칭시켜 데이터를 테이블내에 자동으로 만드는데, 이 이름들은 다른 사람의 컴퓨터 이름과 중복되지 않도록 고유한 이름으로 견지한다. 컴퓨터가 다른 장소로 옮겨지면, IP주소의 서브넷 부분이 변경될 수 있다. WINS를 사용하면 새로운 서브넷 정보가 WINS테이블내에서 자동으로 갱신된다. WINS는 어떤 컴퓨터가 네트워크에 처음정의될 때 IP주소를 협상하는 NT서버의 DHCP를 보충하여 완전하게 한다. 예를 들면 같은 네트워크에서 사람이 많아지면 네트워크에 부하도 많이 발생한다. 이 경우WINS를 사용하면 컴퓨터이름과 IP목록을 관리해주기 때문에 동보통신에 의한 부담을 줄일 수 있다.
30) ; wins server = w.x.y.z
=> wins 서버가 있을 경우 wins server IP값을 지정하는 옵션이다.
31) ; wins proxy = yes
=> nmbd에 의해서 wins기능을 갖추지 못한 호스트들을 대신하여 브로드캐스트 이름 질의를 대신 응답해 줄 수 있도록 지정해 주는 옵션이다. 이것을 사용하려면 네트워크상에 최소 하나 이상의 WINS서버가 있어야 한다.
32) dns proxy = no => nmbd데몬이 wins server역할을 하고, 등록되지 않는 NetBIOS이름을 찾아줄 때 DNS server 를 사용하여 NetBIOS이름을 찾아줄 것인지의 여부를 지정하는 옵션이다.
33) ; case sensitive = no
=> 대소문자를 보존할 필요가 있을 때 설정하는 부분이다.
(2) 공유 정의(Share Definitions) : 삼바 서버에 접속할 수 있는 사용자의 홈디렉토리 설정 1) [homes]
comment = Home Directories
browseable = no
writable = yes
=> 사용자의 홈 디렉토리 서비스 사용을 위한 기본적인 설정을 해주는 항목이다. comment는 간단한 설명문, browseable은 공유이름을 브라우저에 표시할 수 있게 하는 기능, writable은 쓰기허용을 설정한다.
2) [netlogon]
comment = Network Logon Service
path = /home/netlogon
guest ok = yes
writable = no
share modes = no
=> 도메인 로그온을 사용하고자 할 때 사용한다. 일반적으로 사용하지 않는다.
3) [Profiles]
path = /home/profiles
browseable = no
guest ok = yes
=> 특정한 프로파일을 지정할 때 사용한다. 일반적으로 사용하지 않는다.
4) [printers]
comment = All Printers
path = /var/spool/samba
browseable = no
guest ok = no
writable = no
printable = yes
=> 삼바프린터를 네트워크 공유프린터로 사용하고자 할 경우에 설정한다. BSD계열의 프린터 시스템을 사용하면 일일이 프린터를 정의하지 않아도 된다.
5) [tmp]
comment = Temporary file space
path = /tmp
read only = no
public = yes
=> 여러 사람들이 파일을 공유할 목적으로 유효하게 사용할 수 있다. 현재 기본값인 /tmp는 임시작업공간 디렉토리이므로 /var/tmp처럼 다른 디렉토리를 만들어서 사용하도록 한다.
6) [public]
comment = Public Stuff
path = /home/samba
public = yes
read only = yes
write list = @staff
=> 공개적으로 접근이 가능한 디렉토리이지만 staff그룹에 있는 사용자들을 제외한 사용자들은 오직 읽기만 사용가능하다.
7) 사용자정의 섹션
예) [posein]
comment = shared-files in posein directory => 간단한 설명이다.
path = /home/posein/pds => 공유디렉토리의 경로를 지정한다.
read only =no => 공유디렉토리를 읽기만 가능하게 할지를 지정한다.
writable = yes => write ok = yes와 같은 옵션으로 쓰기가 가능하다.
valid user = posein xitem prehee =>서비스디렉토리에 사용가능한 사용자를 말하며, 만약 이 옵션이 생략되면 모든 사용자가 접근할 수 있다.
public = no => guest ok와 같은 옵션으로 no로 설정하면 다른 사용자들은 이용할 수 없고 개인사용자만 사용할 수 있게 된다.
browseable = no => 이용 가능한 공유리스트를 보여줄 것인가를 지정하는 것으로 no로 지정하면 리스트를 보여주지 않는다.
printable = no => 서비스로 지정된 디렉토리에 스풀파일을 지정할 것인가를 지정는 것으로, 프린터 공유 디렉토리가 아니므로 대부분 no로 설정한다.
create mask =0765 => create mode와 같은 옵션으로 파일을 생성할 때 사용되는 모드를 나타낸다.
(참고) samba 에서 공유디렉토리를 지정할 때 사용하는 옵션 설명
- read only : 공유 디렉토리를 읽기만 가능하게 할 것인지를 결정
- writable, write ok : 공유 디렉토리를 쓰기 가능하게 할 것인지를 결정
- valid users : 공유 디렉토리에 로그인할 수 있는 사용자를 결정
- public, guest ok : 다른 사용자들이 이용하게 할 지를 결정
- browseable : 공유 디렉토리의 리스트를 보여줄 지를 결정
- printable : 공유 디렉토리에 스풀 파일을 지정할 것인지를 결정
- path : 공유할 디렉토리의 절대경로를 지정
- comment : 간단한 설명을 적음
- create mask, create mode : 파일을 생성할 때의 모드를 결정. umask값형태로 지정.
- write list : 쓰기가 가능한 특정 사용자를 지정
4. 삼바를 이용하여 공유하기
(1) 리눅스 드라이브를 윈도우와 공유하기
1) /etc/samba/smb.conf파일의 편집
#======================= Global Settings =====================================
[global]
workgroup = WORKGROUP // 윈도우의 워크그룹과 동일한 그룹을 지정한다.
server string = FILE SERVER // 리눅스서버에 대한 설명을 적는다.
hosts allow = 192.168.0. 203.247.51. 127. // 접근허용할 네트워크 범위를 지정한다.
These instructions are for installing kdrive-based X Servers on your system. This does not apply to X.Org at all.
If you're looking for an X server with transparency support, you might consider X.Org since its transparency support is rapidly stabilizing.
If you have some other reason for using the kdrive based server covered here, I'm looking for a replacement maintainer for this page....
It is surprisingly difficult to follow this type of instruction set. You'll have to concentrate and double-check yourself constantly. Good luck!
Unless you're planning to contribute code, you'll usually be better off using packages from your distribution if it has any. Some do. If yours is one of them, feel free and note it here or report it to me (see address at bottom of page.)
These instructions only go as far as the X server and xcompmgr (the eye-candy maker) and the things they require.
If you're getting errors mentioning automake, check that your automake install is recent enough using the commands above.
If you're getting errors mentioning PKG_CHECK_MODULES(), install pkgconfig.
You might also try XserverBuildScript which contains all these instructions in a runnable form.
The KDrive xserver isn't supported in FreeBSD. Anyone interested in porting it is welcome to do so, though.
Note that xcompmgr and window borders don't mix. Most window managers disable window borders but twm users may find that BorderWidth 0 in ~/.twmrc helps.
In case you get an error while compiling such as this:
checking for pkg-config... /opt/gnome2/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for XDMCP... yes
checking for XdmcpWrap in -lXdmcp... yes
checking for XEPHYR... yes
checking for XSERVER... configure: error: Package requirements (randrproto renderproto fixesproto damageproto xextproto xfont xproto xtrans xau compositeproto resourceproto recordproto xdmcp xdmcp) were not met.
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively you may set the XSERVER_CFLAGS and XSERVER_LIBS environment variables
to avoid the need to call pkg-config. See the pkg-config man page for
more details.
*** error during stage configure of xserver: could not configure module *** [32/38]
And rerun the build. It helped here, but it's just a workaround, the real problem is somewhere else. If anyone knows better please fix the real problem instead.
cvs login is no longer required when using cvs.freedesktop.org.
if [ -z "$PKG_CONFIG_PATH" ]; then
export PKG_CONFIG_PATH=/opt/fdo/lib/pkgconfig
else
export PKG_CONFIG_PATH="/opt/fdo/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xproto
pushd Xproto
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xdmcp
pushd Xdmcp
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co XExtensions
pushd XExtensions
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co xtrans
pushd xtrans
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xau
pushd Xau
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co X11
pushd X11
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xext
pushd Xext
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Randr
pushd Randr
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Render
pushd Render
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xrender
pushd Xrender
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xrandr
pushd Xrandr
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co FixesExt
pushd FixesExt
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co DamageExt
pushd DamageExt
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xfont
pushd Xfont
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co ResourceExt
pushd ResourceExt
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co RecordExt
pushd RecordExt
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co CompositeExt
pushd CompositeExt
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co xkbfile
pushd xkbfile
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xserver co xserver
pushd xserver
./autogen.sh --prefix=/opt/fdo --enable-composite
make
sudo install -d /opt/fdo/bin
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xfixes
pushd Xfixes
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xcomposite
pushd Xcomposite
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/xlibs co Xdamage
pushd Xdamage
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
# http://cvs.freedesktop.org/xapps/
wget http://www.freedesktop.org/xapps/release/xcompmgr-1.1.tar.gz
tar zxf xcompmgr-1.1.tar.gz
pushd xcompmgr-1.1
./autogen.sh --prefix=/opt/fdo
make
sudo make install
popd
# to start server, try something like...
sudo /opt/fdo/bin/Xvesa :1 & xterm -display :1
# in xterm...
export LD_LIBRARY_PATH="/opt/fdo/lib:$LD_LIBRARY_PATH"
/opt/fdo/bin/xcompmgr
I use pushd/popd instead of cd/cd .. because it protects against bugs in those install instructions that require directory changes. Fortunately, these are well behaved packages with simple installs.
Interesting XServer Options
-mouse /dev/psaux,5 enables the scroll wheel
-mouse /dev/input/mice,5 for a usb mouse with scroll wheel
-nolisten tcp if you're getting xtrans errors about inet6 or other socket setup things.
-ac -nolisten tcp if you're getting access denied errors when trying to start xterm. Beware this is a security risk, even with -nolisten tcp, so don't do it on a multi-user machine. I've heard some mention that you won't need this if your machine's hostname is set up correctly.
-listmodes lists modes the VESA driver supports
-help lists all these and more
Don't forget the man pages :)
Contacting the Author
This page was originally written by SethKlein on 12-NOV-2003. He no longer uses kdrive and so as of 29-DEC-2004 this page is unmaintained. Please feel free to take up maintainership if you find it useful.
Updated by DiegoEscalante on 10-FEB-2006 while trying to get Xgl working.
Software/Xserver/InstallGuide (2008-08-23 14:10:37에 localhost가(이) 마지막으로 수정)
KDE4's KWin4 Window Manger has built-in 3D-plugins, much like Compiz. Emerge KDE's packages with the xcomposite, where applicable, enabled. See System Settings -> Desktop to enable and configure KDE's Desktop Effects.
KDE 3.x
KDE 3.x's KWin Window Manager has support for composite features provided you set the xcomposite USE-flag when emerging kde-base/kwinand kde-base/kickerfor the split ebuilds or kde-base/kdebaseusing the monolithic ebuilds. Open up KDE Control Center from the KMenu. On the tree on the left, click Desktop->Window Behavior. Click on the Translucency tab and check the Use translucency/shadows option. The various settings are then available for tweaking in the configuration frame. Restarting KDE may be required to enable your new settings.
Note: Make sure you turn off the standard KDE GUI effects (Control Center->Appearance & Themes->Style->Effects->Enable GUI Effects), otherwise the effects will double up and cause strange things to happen.
Enlightenment 0.16
Enlightenment 0.16 supports the composite extension natively, including transparency and shadows and it requires no special USE-flag. In the default configuration it is not enabled, you have to right-click on the desktop and select Composite Settings. Now you are able to control the features for the different windows by right-clicking on the titlebar (the menu where you can set all differnt kinds of window properties. No restart is required.
Enlightenment DR17
Enlightenment DR17 cvs does have a module called Bling for controlling drop shadows and window fades. Just unmask and emerge e_modulesafter emerging e. The module can be activated from Configuration->Modules->Bling.
It is crucial that you issue
enlightenment_remote -use-composite-set 1
as the user who is running e17.
You will also have to deactivate the Dropshadow module in order to get nice shadows which do not interfere with the Bling shadows.
Xfce
Settings -> Window Manager Tweaks -> Compositor
Tools
Fix me: Explain usage of Cairo-Composite-Manager instead of XCompMgr.
xcompmgr
Warning: xcompmgr is a proof of concept application and is not meant for daily use. It is known to have memory leak issues, see bug 150348.
emerge -a xcompmgr
At this point we have all we need to enable drop shadows, cool "fade out" effects and real transparency. First we need to launch xcompmgr. From a console inside of X.Org do this:
xcompmgr -c
This will let you see the effects of running xcompmgr - if you don't like them, just type Ctrl+c from the console you are running xcompmgr in. If you do like them, type Ctrl+c and then:
xcompmgr -c &
The & asks xcompmgr to run in the background - when it's started this way you will have to use kill or killall to stop xcompmgr.
Note: Rather than doing Ctrl+c and killing the program you can also Crtl+z to suspend the program momentarily and type bg to put the process in the background without having to use &. Background jobs can be listed with the jobs command and killed with thekill %1 command where 1 is the number listed in the 'jobs' command output. Note that after suspending composite manager your screen will freeze until you type 'bg'.
This will enable xcompmgr with soft drop shadows turned on. You should now have happy little drop shadows on all your windows. You could optionally use the -s flag instead for hard shadows.
Here are some example settings for xcompmgr with shadow and fading,
xcompmgr -cCfF -r7 -o.65 -l-10 -t-8 -D7 &
To disable all of this after you have got it going, simply type this in a console,
killall xcompmgr
This will turn xcompmgr off, and disable all drop shadows and transparency settings.
transset
Note: You will need to have xcompmgr running for transset to work.
To enable transparent window, you'll need to tool x11-misc/transset,
emerge -a transset
Note: You will need to have xcompmgr running for transset to work.
Run in a terminal,
transset
Now your cursor will have changed, simply click on the window you want to make see through. You can also pass transset a value to define how transparent to make the windows, where 0 is fully transparent and 1 is fully opaque. Try:
transset .2
transset-df
Note: You will need to have xcompmgr running for transset-df to work.
If you don't want to wait and transset is not too handy for you, you can use x11-misc/transset-df,
emerge -a transset-df
Then, you can use keyboard or mouse shortcuts to set the transparency value to the focused windows.
The scroll wheel method can be realized via xbindkeys.
emerge -a xbindkeys
File: ~/.xbindkeysrc
"transset-df --min 0.1 -p --dec 0.2"
control + b:4
"transset-df -p --inc 0.1"
control + b:5
This way you can adjust the transparency of any window dynamically.
Troubleshooting
Performance
To increase performance, add to your /etc/X11/xorg.conf,
When enabled, you will find the following lines in your xorg log file /var/log/Xorg.0.log:
File: /var/log/Xorg.0.log
(**) (0): Option "BackingStore" "true"
(**) (0): Backing store enabled"
This option is used to enable the server's support for backing store, a mechanism by which pixel data for occluded window regions is remembered by the server thereby alleviating the need to send expose events to X clients when the data needs to be redisplayed. This can significantly increase performance.
Within the IPv4 networked world Network Address and Port Translation (NAPT, but also called NAT) between a public IPv4 address and a private IPv4 address was created around 2001 to address the ongoing depletion of the public IPv4 address pool. Another solution to resolve address depletion was a technology identified as VLSM (variable length subnet Masks) and served as a good short term solution. The long term solution for IPv4 address exhaust resulted in a forklift IP upgrade from IPv4 towards IPv6.
This paper will discuss briefly traditional IPv4 address translation, followed with some elements of cross IPv4 and IPv6 NAT translation solutions, including the historical NAT-PT solution.
What is in this paper:
• IPv4-IPv4 Address translation-NAPT (also known as NAT44)
IPv4 Network Address and Port Translation (IPv4 NAT and NAPT)
The IPv4 network address and port translation (NAPT, RFC3022) we all know is mainly based upon private IPv4 addresses space towards public IPv4 address space. This is utilized most frequently at residential Home-Gateways during last decade and is a stateful technology. It is stateful because each translation creates state within the NAPT device, necessary for the return packet to be routed. The initial purpose of NAPT was to multiplex many users in a single IPv4 address on the global Internet. The example shown here is with Cisco NAT (with overload technology) where many devices using private RFC1918 addresses on the inside of the NAT44 can use a single global unique IPv4 address to communicate on the global IPv4 Internet. The Cisco Command Line Interface (CLI) shown below gives an indication of the stateful mapping between the inside and outside IP addresses and port numbers used.
Table 1. Stateful Mapping Between the Inside and Outside IP Addresses and Port Numbers
Router# show ip nat translations
Pro Inside global Inside local Outside local Outside global
The usage of an IPv4 Network Address Translator device goes from the assumption that the L4 protocol used is either UDP or TCP, and that the two communicating end-stations support IPv4 as protocol.
An important issue of NAPT isn't so much on "what amount of memory do you need" or "what is the lookup time in the implied data structure". The issue is the effect on applications. As a result of NAPT, we can't put publicly-accessible applications behind the firewall, and have to think about their security separately.
The first solution the IETF (Internet Engineering Task Force-www.ietf.org) developed to allow IPv4 `ONLY' hosts to speak to IPv6 `ONLY' hosts and vice versa is known as NAT-PT (RFC2766). This first translation solution between IPv4 and IPv6 existed out of mainly two parts:
• Domain Name System (DNS) Application Level Gateway (ALG)
– When a IPv6 user does a DNS name query for a device with only IPv4 connectivity (ie. www.foo4.com), then the DNS request must be translated from being a IPv6 DNS request towards a IPv4 DNS request. This is a function achieved by the DNS ALG embedded within the NAT-PT technology.
– Similar when a IPv4 only user does a DNS name query for a device with only IPv6 connectivity the DNS ALG embedded in the NAT-PT translates this DNS request
• Address Family Translation (AFT)
– When an IPv6-only device wants to send an IPv6 data packet to an IPv4-only device then, there is need for a translation of the IPv6 protocol header into a IPv4 protocol header so that the recipient device can understand the data. On the return path after the IPv4-only device sends a response packet, a translation is needed from IPv4 towards IPv6, so that the IPv6-only device can understand the response packet.
– The foundational algorithm of the IPv4/IPv6 protocol translation used within NAT-PT is based upon a technology called "Stateless IP/ICMP Translator" also known as SIIT (RFC2765). This same technology describes also the IPv6-initiated IPv6-to-IPv4 protocol translation known as stateless NAT64.
Over the years NAT-PT usage has proven as technology to be too complex to maintain scalable translational services, resulting in it being declared historical (RFC4966-Reasons to Move the Network Address Translator-Protocol Translator (NAT-PT) to Historic Status). However, translational technology has been made more modular and segmented, and replacements for translations between IPv6 and IPv4 have been created within a focussed translation framework by the IETF in the Behave working group (http://datatracker.ietf.org/wg/behave/charter/).
Stateless NAT64-Stateless translation between IPv4 and IPv6
RFC6145 (IP/ICMP Translation Algorithm) replaces RFC2765 (Stateless IP/ICMP Translation Algorithm (SIIT)) and provides a stateless mechanism to translate a IPv4 header into an IPv6 header and vice versa. Due to the stateless character this mechanism is very effective and highly fail safe because more as a single-or multiple translators in parallel can be deployed and work all in parallel without a need to synchronize between the translation devices.
The key to the stateless translation is in the fact that the IPv4 address is directly embedded in the IPv6 address. A limitation of stateless NAT64 translation is that it directly translates only the IPv4 options that have direct IPv6 counterparts, and that it does not translate any IPv6 extension headers beyond the fragmentation extension header; however, these limitations are not significant in practice.
With a stateless NAT64, a specific IPv6 address range will represent IPv4 systems within the IPv6 world. This range needs to be manually configured on the translation device. Within the IPv4 world all the IPv6 systems have directly correlated IPv4 addresses that can be algorithmically mapped to a subset of the service provider's IPv4 addresses. By means of this direct mapping algorithm there is no need to keep state for any translation slot between IPv4 and IPv6. This mapping algorithm requires the IPv6 hosts be assigned specific IPv6 addresses, using manual configuration or DHCPv6.
Stateless NAT64 will work very successful as proven in some of the largest networks, however it suffers from some an important side-effect: Stateless NAT64 translation will give an IPv6-only host access to the IPv4 world and vice versa, however it consumes an IPv4 address for each IPv6-only device that desires translation -- exactly the same as a dual-stack deployment. Consequentially, stateless NAT64 is no solution to address the ongoing IPv4 address depletion. Stateless NAT64 is a good tool to provide Internet servers with an accessible IP address for both IPv4 and IPv6 on the global Internet. To aggregate many IPv6 users into a single IPv4 address, stateful NAT64 is required.
NAT64 are usually deployed in conjunction with a DNS64. This functions similar to, but different than, DNS-ALG that was part of NAT-PT. DNS64 is not an ALG; instead, packets are sent directly to and received from the DNS64's IP address. DNS64 can also work with DNSSEC (whereas DNS-ALG could not).
Stateful NAT64-Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers
Stateful NAT64 multiplexes many IPv6 devices into a single IPv4 address. It can be assumed that this technology will be used mainly where IPv6-only networks and clients (ie. Mobile handsets, IPv6 only wireless, etc...) need access to the IPv4 internet and its services.
The big difference with stateful NAT64 is the elimination of the algorithmic binding between the IPv6 address and the IPv4 address. In exchange, state is created in the NAT64 device for every flow. Additionally, NAT64 only supports IPv6-initiated flows. Unlike stateless NAT64, stateful NAT64 does `not' consume a single IPv4 address for each IPv6 device that wants to communicate to the IPv4 Internet. More practically this means that many IPv6-only users consume only single IPv4 address in similar manner as IPv4-to-IPv4 network address and port translation works. This works very well if the connectivity request is initiated from the IPv6 towards the IPv4 Internet. If an IPv4-only device wants to speak to an IPv6-only server for example, manual configuration of the translation slot will be required, making this mechanism less attractive to provide IPv6 services towards the IPv4 Internet.
DNS64 is usually also necessary with a stateful NAT64, and works the same with both stateless and stateful NAT64.
Summary
While stateful and stateless NAT64 perform the task of translating IPv4 packets into IPv6 packets and vice versa, there are important differences as explained in previous sections. The following table provides a high-level overview of the most relevant differences.
Table 2. Differences Between Stateless NAT64 and Stateful NAT64
Stateless NAT64
Stateful NAT64
1:1 translation
1:N translation
No conservation of IPv4 address
Conserves IPv4 address
Assures end-to-end address transparency and scalability
Uses address overloading, hence lacks in end-to-end address transparency
No state or bindings created on the translation
State or bindings are created on every unique translation
You can load the corespondig modules automaticaly by adding them to /etc/modules.autoload.d/kernel-2.6, if you do not want the modules to be loaded at boot, you can load them with the modprobe commando.
I prefer using this card with the xine player. You must have dvb in your useflags defined, so that anemerge xine-lib xine-ui compiles the dvb-plugin for xine. After putting a channels.conf in ~/.xine you can start xine, with a click on dvb you should be able to watch tv now. To switch beetween the channels you can try to use your mousewheel, or deaktivate Numlock and use the keys 8 and 2!
File: /~/.xine/channels.conf
:-Astra 19,2 E--
Das Erste:11837:h:0:27500:101:102:0:0:28106
ZDF:11954:h:0:27500:110:120:0:0:28006
3sat:11954:h:0:27500:210:220:0:0:28007
EinsMuXx:12110:h:0:27500:301:302:0:0:28203
EinsExtra:12110:h:0:27500:101:102:0:0:28201
EinsFestival:12110:h:0:27500:201:202:0:0:28202
MDR FERNSEHEN:12110:h:0:27500:401:402:0:0:28204
RBB Brandenburg:12110:h:0:27500:501:502:0:0:28205
RBB Berlin:12110:h:0:27500:601:602:0:0:28206
SWR Fernsehen:11837:h:0:27500:801:802:0:0:28113
SR Fernsehen Suedwes:11837:h:0:27500:501:502:0:0:28110
SDWEST RP:12110:h:0:27500:3101:3102:3104:0:28231
hessen fernsehen:11837:h:0:27500:301:302:0:0:28108
WDR K ln:11837:h:0:27500:601:602:0:0:28111
Bayerisches FS:11837:h:0:27500:201:202:0:0:28107
NDR FS MV:12110:h:0:27500:2401:2402:0:0:28224
BR-alpha:11837:h:0:27500:701:702:0:0:28112
KiKa:11954:h:0:27500:310:320:330:0:28008
arte:11836:h:0:27500:401:402:404:0:28109
ZDF Theaterkanal:11954:h:0:27500:1110:1120:0:0:28016
ZDF.info:11954:h:0:27500:610:620:0:0:28011
ZDF.doku:11954:h:0:27500:660:670:0:0:28014
Phoenix:11837:h:0:27500:901:902:0:0:28114
DW-TV:11597:v:0:21997:1000:1001:0:0:10020
MDR THRINGEN:12110:h:0:27500:401:402:0:0:28230
MDR S-ANHALT:12110:h:0:27500:401:402:0:0:28229
MDR SACHSEN:12110:h:0:27500:401:402:0:0:28228
NDR FS SH:12110:h:0:27500:2401:2402:0:0:28227
NDR FS NDS:12110:h:0:27500:2401:2402:0:0:28226
NDR FS HH:12110:h:0:27500:2401:2402:0:0:28225
WDR D sseldorf:12422:h:0:27500:101:102:0:0:28308
WDR Essen:12422:h:0:27500:101:102:0:0:28309
WDR Dortmund:12422:h:0:27500:101:102:0:0:28307
WDR Bielefeld:12422:h:0:27500:101:102:0:0:28306
WDR Siegen:12422:h:0:27500:101:102:0:0:28311
WDR Wuppertal:12422:h:0:27500:101:102:0:0:28312
WDR M nster:12422:h:0:27500:1a01:102:0:0:28310
WDR Aachen:12422:h:0:27500:101:102:0:0:28305
:-- Free TV D --
RTL Television:12188:h:0:27500:163:104:0:0:12003
SAT.1:12480:v:0:27500:1791:1792:0:0:46
ProSieben:12480:v:0:27500:255:256:0:0:898
RTL2:12188:h:0:27500:166:128:68:0:12020
Super RTL:12188:h:0:27500:165:120:0:0:12040
KABEL1:12480:v:0:27500:511:512:0:0:899
VOX:12188:h:0:27500:167:136:71:0:12060
BTV:12226:h:0:27500:512:660:0:0:31210
TELE 5:12480:v:0:27500:1535:1536:38:0:51
TV.BERLIN:12149:h:0:27500:511:512:0:0:772
XXP:12631:h:0:21995:203:303:503:0:12602
ONTV Regional:12149:h:0:27500:2303:2304:0:0:514
Franken SAT:12149:h:0:27500:3583:3584:0:0:775
rhein main tv:12633:h:0:22000:208:308:508:0:12614
NEUN LIVE Televisi:12480:v:0:27500:767:768:0:0:897
Bloomberg TV Germany:12552:v:0:22000:162:99:0:0:12160
EuroNews:11954:h:0:27500:2221:2233:0:0:28015
EURONEWS:11817:v:0:27500:163:99:0:0:8004
N24:12480:v:0:27500:2047:2048:0:0:47
n-tv:12670:v:0:22000:162:96:55:0:12730
DSF:12480:v:0:27500:1023:1024:0:0:900
Eurosport:11954:h:0:27500:410:420:0:0:28009
Bahn TV:12631:h:0:21995:201:301:0:0:12600
TV6:12610:v:0:22000:100:101:4201:0:12301
RAZE TV:10832:h:0:22000:308:256:0:0:61963
HOERZU DIGITAL:10832:h:0:22000:5169:8191:0:0:61961
Bibel TV:10832:h:0:22000:32:33:0:0:61900
K-TV:12631:h:0:21995:202:302:0:0:12601
Home Order Tel:12480:v:0:27500:1279:1280:0:0:40
QVC GERMANY:12552:v:0:22000:165:166:0:0:12100
RTL Shop:12188:h:0:27500:168:137:70:0:12080
TV TRAVEL SHOP:12149:h:0:27500:1023:1024:37:0:769
lastminute.de:12149:h:0:27500:3071:3072:0:0:54
Sonnenklar TV:12480:v:0:27500:2303:2304:0:0:32
K1010:12631:h:0:21995:1041:1042:0:0:12616
Spielekanal TV:12631:h:0:21995:1053:1054:1055:0:12618
OTTO SHOP:12460:h:0:27500:255:8191:0:0:901
VIC-TV.NET DE1:12460:h:0:27500:511:8191:0:0:60
VIC-TV.NET DE2:12460:h:0:27500:767:8191:0:0:61
TW 1:12692:h:0:22000:166:167:0:0:13013
SAT.1 A:12051:v:0:27500:800:801:802:0:20005
SAT.1-CH:12149:h:0:27500:255:256:34:0:48
GOD Channel:12149:h:0:27500:767:768:0:0:774
RNFplus:12149:h:0:27500:1104:1105:0:0:768
ProSieben A:12051:v:0:27500:161:84:0:0:20002
ProSieben CH:12051:v:0:27500:289:290:0:0:20001
Kabel 1 Austria:12051:v:0:27500:166:167:0:0:20004
Kabel 1 Schweiz:12051:v:0:27500:162:163:0:0:20003
RTL Austria:12226:h:0:27500:201:202:203:0:28800
VOX Austria:12226:h:0:27500:301:302:303:0:28805
RTL2 Austria:12226:h:0:27500:401:402:403:0:28810
Super RTL A:12226:h:0:27500:501:502:503:0:28815
:-- Free TV INT --
CNN Int.:11778:v:0:27500:165:100:0:0:28522
Al Jazeera:11568:v:0:22000:55:56:0:0:9021
Sky News:11597:v:0:22000:305:306:0:0:28707
BBC WORLD:12285:v:0:27500:167:108:0:0:17027
2M Maroc:11568:v:0:22000:139:140:0:0:9030
TV TWRAM:10832:h:0:22000:70:71:0:0:61911
Free-X TV:10832:h:0:22000:160:80:0:0:61980
Ocko TV:10832:h:0:22000:161:162:0:0:61990
CANAL CANARIAS:10979:v:0:22000:164:96:0:0:30661
CCVALENCIANA:11436:v:0:22000:169:116:0:0:29912
OKplus:11509:v:0:22000:100:8191:0:0:30100
CANAL ALGERIE:11568:v:0:22000:168:138:0:0:9011
TV7:11568:v:0:22000:166:128:0:0:9018
TV 5:11568:v:0:22000:164:112:0:0:9012
ESC1 - EGYPT:11568:v:0:22000:163:104:0:0:9014
RAI 1:11568:v:0:22000:289:290:0:0:9015
RTPI:11568:v:0:22000:161:301:0:0:9017
ARTE:11568:v:0:22000:167:136:0:0:9019
Eurosport News:11597:v:0:22000:1000:1001:0:0:10011
TVEi:11597:v:0:22000:50:51:0:0:10001
RTM MAROC:11597:v:0:22000:63:62:0:0:10002
ETB SAT:11686:v:0:22000:163:92:0:0:30203
TVC INT.:11686:v:0:22000:161:84:35:0:30201
ANDALUCA TV:11686:v:0:22000:162:88:38:0:30202
TV GALICIA:11686:v:0:22000:167:108:53:0:30222
TM SAT/LA OTRA:11686:v:0:22000:164:96:44:0:30204
Travel:11778:v:0:27500:163:92:0:0:28003
hollywood cinema:12460:h:0:27500:1023:1024:0:0:663
LA CINQUIEME:12207:v:0:27500:160:80:0:0:8501
LCP:12207:v:0:27500:165:100:0:0:8506
BEUR TV:12324:v:0:27500:167:108:0:0:8613
Chamber TV:12552:v:0:22000:55:56:0:0:12180
RTL TELE Letzebuerg:12552:v:0:22000:168:144:74:0:3994
Club Teleachat:12611:v:0:22000:53:54:0:0:12270
RTBF SAT:12610:v:0:22000:48:49:0:0:3982
CNBC Europe:12611:v:0:22000:944:945:0:0:12200
LibertyTV.com:12611:v:0:22000:941:942:0:0:12280
TV5 Europe:12611:v:0:22000:45:46:0:0:12240
Motors TV:12611:v:0:22000:191:194:0:0:12300
version 2.20 글쓴이 : (주)리눅스랩 대표이사 배철수<churl_nospam@linuxlab.kr> - 메일 보낼때는 _nospam 을 빼야 한다.
사용자는 자신의 판단으로 아래 프로그램 설치 및 사용 여부를 결정해야 한다. 아래 설정으로 인해 리눅스 호스트의 오작동, 데이타 손실 등 어떠한 물적, 정신적 손해가 발생되도 이는 이 프로그램을 설치한 사람 자신의 책임이다.
설치가 제대로 안된다고 PC를 발로 걷어차서 PC가 부서지거나 발가락이 삐는것, 머리카락을 쥐어 뜯어 대머리가 되는것, 또 밤새 설치하다가 늦잠자서 회사에 지각해 상사에게 꾸지람 듣고 홧김에 술마시고 음주운전하다 벌금을 무는 등의 일체의 간접적인 손해도 역시 본인의 책임이 아니다.
. 이 글에서 리눅스 client 란 리눅스랩의 pptp VPN 서버를 연결하는 사용자 측 리눅스 호스트를 말한다. . 이텔릭체로 표시한 부분은 사용자가 입력하는 명령이다. (뒤에 <Enter> 키를 눌러야 한다.) . 회색 바탕은 리눅스 client 의 화면 출력이다.
[사족]
리눅스랩의 라이브라 장비를 사용해서 리눅스랩과 동일한 VPN 고정 IP 서비스를 하는 다른 업체의 VPN 연결에는 설정을 사용할 수 없다. VPN 연결은 되지만 인터넷에서 리눅스 호스트를 접속할 수 없다.
아래 설명은 데비안 배포본을 기준으로 한다.
리눅스 전문가라면 아래 설명을 보지 않고도 pptp 를 연결할수 있다. 아래 설명을 읽고도 pptp 를 연결하지 못한다면 리눅스를 사용하지 말고 윈도우를 사용하기를 권한다.
위의 w.x.y.z 에는 리눅스랩에서 할당하는 공인 IP를 입력하는게 아니다. 할당한 IP 는 pptp 가 연결이 될 경우에 client 에서 받는 IP 주소이다. 서버 주소는 리눅스랩 홈페이지(pptp.kr)에 나오는 VPN 서버의 IP 주소를 입력해야 한다. (도메인 네임은 사용할 수 없다.)
공인 IP 는 반드시 지정된 서버만 접속해야 한다.
*. 만약 ADSL 라인을 pppoe 방식으로 리눅스 client 에 연결했다면 /etc/ppp/peers/linuxlab 파일에 아래 라인을 추가한다.
mtu 1452
*. vi 편집기를 사용할 줄 모르면 pico 나 nano 를 사용하면 된다. 리눅스에서 편집이 어려우면 ftp 로 다운 받은 후 윈도우에서 수정한다. 단 윈도우로 다운 받거나 윈도우에서 리눅스로 업로드할 때 ftp 에서 꼭 ascii 옵션을 사용해야 한다. 아래와 같다. (윈도우에서 pptpc 파일을 업로드 했으면 필히 "chmod 755 pptpc" 명령을 줄것.)
230 User admin logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ascii
200 Type set to A
연결
/etc/ppp/pptpc 명령을 실행한다.
연결 확인
ifconfig 명령을 주었을 때 아래처럼 나와야 한다.(일부 생략)
ppp? Link encap:Point-to-Point Protocol
inet addr:999.999.999.999 P-t-P:w.x.y.z Mask:255.255.255.255
*. ip 명령을 사용한다면 ip addr sh 명령을 주면 아래처럼 나온다.
14: ppp0: mtu 1500 qdisc pfifo_fast qlen 3
link/ppp
inet 999.999.999.999 peer w.x.y.z scope global ppp0
*. 999.999.999.999 대신 자신에게 할당된 IP 주소가 나와야 한다.
ps ax 명령을 줄 때 아래 3 줄이 나와야 한다.
16254 ? Ss 0:00 /usr/sbin/pppd ipparam linuxlab name ????? call linuxlab
16255 ? S 0:00 pptp: GRE-to-PPP gateway on /dev/ptmx
16289 ? S 0:00 pptp: call manager for w.x.y.z
(or 629 ? S 0:00 pptp: call manager for 220.--nolaunchpppd)
*. ????? 대신 자신의 VPN 계정이 나와야 한다. *. "16254" 는 Process ID 로서 VPN 연결을 끊을 때 필요하다.
위 라우팅 테이블은 리눅스랩 방화벽 밑에서 VPN 을 연결한 경우이다. 인터넷 라인(방화벽)은 eth1 에 연결돼 있다.
4 번째 줄의 "172.29.0.1" 은 VPN 서버의 IP 이다. 어느 서버를 연결하느냐에 따라 다르다.
5 번째 줄의 192.168.0.0 은 방화벽 과 리눅스 client 간의 내부 네트워크 주소이다.
리눅스 네트워킹에 대해 조금 알고 있는 리눅서라면 위의 라우팅 테이블이 이상하다고 느낄 것이다.
*. 이상하지 않다고 생각했다면 리눅스 네트워킹에 대한 전문가이거나 문외한 중 하나이다.
왜 디폴트게이트웨이 인터페이스(마지막 줄)가 eth1 인지 의아해 할것이다. default gateway 가 VPN 인터페이스(ppp0) 여야 하지 않는가? 라우팅 테이블이 틀리지 않은가?
천만에요. 이걸 비대칭 라우팅이라고 부르는 겁니다. 일반적으로 거의 사용하지 않는 어려운 기법입니다. (비대칭 라우팅은 개념이 어려워 여기서 설명하지 않습니다.)
외부에서 리눅스랩에서 받은 IP 주소로 telnet 이나 ssh 로 연결해 보세요.
부팅시 vpn 자동 연결
위의 연결 명령을 리눅스 boot 스크립트에 넣어야 리부팅시 자동으로 VPN 이 연결된다.
Redhat
/etc/rc.d/rc.local 파일의 맨 뒤에 아래 라인을 넣는다.
/etc/ppp/pptpc
Debian
ln -s /etc/ppp/pptpc /etc/rc.boot/pptpc 명령 실행
또는 /etc/ppp/pptpc 을 /etc/rc.boot 에 복사한다.
SuSE
/etc/init.d/boot.local 파일의 맨 뒤에 /etc/ppp/pptpc 라인을 추가한다.
주의 : 다른 배포본 또는 customized 된 시스템에서 연결시 VPN 연결 명령(pptpc)이 인터넷 연결 프로그램 보다 나중에 실행되야 한다.
자동 재연결
인터넷 라인이 끊기면 VPN 연결도 같이 끊긴다. 또는 공유기를 사용시 공유기를 껏다 켜도 VPN 연결은 끊긴다. VPN 연결이 끊겨도 자동으로 재 접속되게 하려면 crontab 에서 /etc/ppp/chk-vpn 파일을 1분에 한번씩 자동으로 실행되게 해야 한다.
crontab -l 명령을 주면 현재 crontab 에서 실행 되는 명령이 나온다. 아무런 설정이 없다면 아래 명령을 준다.
crontab /etc/ppp/cron-pptpc <enter>
crontab 에 이미 다른 설정이 있다면 crontab -e 명령으로 crontab 에 아래 라인을 추가한다.
*/1 * * * * /etc/ppp/chk-vpn
각 항목 다음에 반드시 공백이 한 개 이상 필요하다.
확인하려면 crontab -l 명령을 준다. 아래처럼 나와야 한다.
*/1 * * * * /etc/ppp/chk-vpn
*. crontab 설정 확인 : crobtab -l *. crontab 설정 제거 : crontab -r
장애 처리
VPN 연결이 안된다.
공유기를 사용한다면 공유기가 "VPN (ppTp) pass through" 기능을 지원하는지 확인할 것.(공유기/방화벽 사용에 대해서는 자주 받는 질문 "3" 번을 참고하시오.) : 공유기 문제인지 확인하려면 공유기를 떼고 연결을 시도하던지 또는 윈도우에서 VPN 연결을 시도해 본다.
/etc/ppp/options 파일을 지우고 연결을 시도한다.
man pppd 명령을 주어서 옵션에 -defaultroute 가 있는지 확인해 본다. 오래된 배포본의 경우 -defaultroute 대신 nodefaultroute 를 사용하는 경우도 있다. 이 경우는 /etc/ppp/peers/linuxlab 파일의 -defaultroute 를 nodefaultroute 로 변경
그래도 안되면 /etc/ppp/options 파일에 debug 을 넣고 연결을 시도한다. 그러면 /var/log/debug(or syslog : 배포본 마다 다르다) 파일에 ppp 와 관련된 로그가 저장된다. 그 로그를 자세히 보면 어디엔가 에러 원인이 나타난다
이 글 맨 뒤에 정상적으로 연결되었을 때의 /var/log/debug 파일 내용을 첨부했다. 이 로그와 비교해서 차이가 있는지 본다. 로그에 "Welcome to libra." 가 안나오면 계정 또는 패스워드가 틀렸다.
VPN 연결은 되는데 자주 끊긴다.
- 공유기가 "VPN (ppTp) pass through" 기능을 제대로 지원하는지를 확인할 것.
- 윈도우 PC에서 VPN 을 연결해도 마찬가지 인지를 비교해 볼것.
- 라인 상태를 점검해 본다. 리눅스랩 VPN 서버 IP 주소 또는 사용하는 인터넷 라인의 ISP 의 DNS 서버 주소로 ping 테스트를 해 본다.
일부 사이트가 열리지 않거나 큰 파일 다운로드시 속도가 느리다.
- /etc/ppp/peers/linuxlab 파일에 아래 라인을 추가해 본다.
mtu 1432 (또는 mtu 1400)
VPN 연결은 되는데 외부에서 리눅스 client IP 주소로 접속(ping)이 안된다.
/sbin/ip route show 명령을 줄 때 에러가 뜨는지를 볼것. : 에러가 뜨면 iproute 프로그램을 재설치한다.
방화벽 룰이 설정되었는지를 확인할것.(iptables -vnL) 방화벽 룰을 제거하고(아래 명령) 연결을 시도해 본다.
iptables -F
dmesg 명령을 실행해서 에러가 나오는지를 볼것
혹시 아래와 비슷한 에러가 나오면 이는 배포본, 커널, 모듈 문제이므로 해결이 쉽지 않다.
divert: no divert_blk to free, ppp0 not ethernet divert: not allocating divert_blk for non-ethernet device ppp0
<해결 방법>
- 아래 두 명령을 실행해 본다.(아래 명령은 한 줄이다. \는 명령을 두 줄로 계속할 때 사용한다.)
(1) /sbin/iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --clamp-mss-to-pmtu (2) /sbin/iptables -A OUTPUT -p tcp --tcp-flags SYN,RST SYN \ -j TCPMSS --clamp-mss-to-pmtu
- 랜카드 드라이버를 모듈로 올리지 말고 커널을 컴파일해 넣는다.
인터넷 라인이 끊겼다 다시 연결됐는데 pppd 데몬이 종료하지 않아서 VPN 자동 재연결이 안된다.
linuxlab 파일에는 pppd 옵션을 지정하는 부분이 들어 있다. 이중 lcp-echo-interval 과 lcp-echo-failure 는 VPN 연결이 비정상 종료(라인 절단)인 경우에 pppd 데몬을 종료케하는 부분이다.
lcp-echo-interval 은 몇 초에 한 번 VPN 서버로 연결 확인(LCP Echo) 을 할것인지를 지정한다. lcp-echo-failure 는 LCP Echo 가 몇 번 실패할 경우에 pppd 데몬을 종료할 것인지를 지정한다. lcp-echo-interval 30 이고 lcp-echo-failure 가 4 라면 라인 연결이 끊기면 약 120 초 이내에 pppd 데몬이 종료한다. 그러면 crontab 에서 chk-vpn 스크립트가 pppd 데몬이 종료했으므로 pptpc 스크립트를 실행해서 VPN 을 다시 연결해 준다.
그러나 극히 드믈지만 위의 두 옵션에서 pppd 데몬이 죽지 않는 경우도 있다. 이럴 때를 대비해 만든 옵션이 있는데 바로 idle 이다. "idle 240" 을 linuxlab 에 추가하면 이 문제를 해결할 수 있다. 이 옵션은 240초 동안 전혀 데이타 이동이 없으면(LCP Echo 포함) pppd 를 종료하라는 뜻이다.
모든 방법을 동원해도 연결이 안되면 /etc/ppp/options 파일에 debug 를 넣고 연결을 시도 후 /var/log/debug 파일 내용[참고 4]을 vpn@linuxlab.co.kr 로 보내기 바란다.
그리고 공유기에서 23/tcp(또는 22/tcp) 를 리눅스 client 로 포트포워딩을 설정하고 리눅스에서 telnet(ssh) 데몬을 가동하면 리눅스랩에서 원격으로 접속하여 모든 설정을 해 줌.(비용 없슴.)
[참 고]
리눅스랩 VPN 을 연결해서 메일 서버를 운영하는데 한메일 같은 일부 포탈 사이트로 보낸 메일이 스팸으로 처리된다는 불평을 하는 사람이 있다. 이는 비대칭 라우팅을 이해하지 못하기 때문이다.
한메일에서 리눅스 메일 서버로 보내는 메일은 VPN 으로 받은 IP 주소로 들어온다. 하지만 윈도우에서 Outlook 로 리눅스 메일 서버를 지정해 메일을 보내면 리눅스 메일 서버가 일단 저장 한 후 이를 다른 메일 서버(한메일 메일서버)로 보낸다.
리눅스 메일서버가 비대칭 라우팅을 사용한다면 메일이 나갈 때는 리눅스랩에서 VPN 으로 받은 IP 주소가 사용되지 않고 공유기 또는 리눅스에 연결된 ADSL/케이블 라인의 IP 주소로 나간다.
만약 메일 수신자측 메일 서버가 메일 헤더에 있는 도메인 네임을 nslookup 하면 리눅스랩의 VPN IP 주소가 나올것이다. 그런데 메일헤더에 있는 IP 주소는 VPN IP가 아닌 ADSL 라인의 IP 이다. 일부 포탈사이트는 이 둘이 같지 않으면 스팸으로 처리한다.
불특정 다수에게 메일을 발송하는 경우라면 [참고 1] 에 나온 것처럼 비대칭 라우팅이 아닌 방식을 사용하기 바란다. 단 이 경우는 속도에서 손해를 본다. 리눅스 메일 서버에서 메일이 나갈 때 ADSL/케이블 라인의 속도가 아닌 리눅스랩 VPN 서버에서 지정한 속도가 적용되기 때문이다. (리눅스랩 VPN 서버는 대역폭 제어를 한다.)
연결 끊기
위의 6. 2) 첫번째 줄 맨 앞에 나오는 프로세스 ID를 kill 한다.
kill -9 16254
공유기(NAT gateway) 사용
공유기 사용자는 필히 자주 받는 질문을 참고하기 바란다. 리눅스를 NAT gateway 로 사용하는 경우도 마찬가지다.
기 타
위의 설정은 리눅스 client 에서 웹/메일/DB 등의 서버를 운영할 경우에 적합하다. 즉 위의 설정으로 연결하면 외부에서 리눅스 client 의 VPN 으로 받은 고정 IP 주소로 연결시만 VPN 링크가 사용된다.
리눅스 client 에서 인터넷을 사용할 경우 또는 리눅스 client 를 게이트웨이로 지정해서 인터넷을 사용하는 피시에서 인터넷을 사용시는 VPN 으로 부여 받은 고정 IP가 사용되지 않고 리눅스 client 에 연결된 인터넷 라인의 IP(공유기 사용시는 공유기에 부여된 IP 주소) 가 사용된다.
(비대칭 라우팅으로 불린다. 왜 그렇게 되는지 설명하려면 너무 길다.). [참고 3]을 보면 default gateway 가 공유기의 주소 즉 192.168.0.1 이다.
사용자의 입장에서는 리눅스 client 에서 데이타가 나가는 경우에는 VPN 서버를 거치지 않는게 유리하다. 왜냐하면 VPN 서버를 거치면 서버에서 대역폭 제어를 하므로 해당 라인의 최고 속도를 사용할 수 없다.
따라서 이 설정을 효과적으로 사용하려면 VPN Pass Through 기능이 있고 Multi-Session 을 지원하는 공유기(Dlink 사의 DI-604 등)에 인터넷 라인을 연결하고, 리눅스 client 에는 사설 IP(192.168.x.x)를 부여해서 리눅스 client 의 디폴트 게이트웨이를 공유기의 랜 포트의 주소를 주면 된다.
공유기 설정에서 공유기에 연결된 피시의 IP 를 자동으로 부여 하지 말고 수동으로 부여해야 한다. 아니면 공유기에서 IP 자동 부여를 하되 VPN 을 연결하는 리눅스 client IP 를 자동 부여 IP 목록에서 제외한다.
물론 위의 설정은 리눅스 client 에 직접 ADSL/케이블/전용선을 연결할 경우에도 작동한다.
위의 설정은 VPN을 연결한 리눅스 client 에서 인터넷을 연결하는 경우는 VPN IP를 사용하지 않는다.(비대칭 라우팅이라 불린다.) 리눅스랩의 VPN 서버는 대역폭 제어(QOS)를 하는데, 리눅스 client 에서 인터넷을 연결할 때도 VPN 으로 받은 IP 주소를 사용하려면 데이타가 VPN 서버를 거쳐야 하고, 그 경우 업로드/다운로드 속도가 VPN 서버에서 지정한 속도로 제한을 받기 때문이다.
즉 "개인 IP" 512k 서비스를 신청했다면 VDSL 10 메가 라인을 사용해도 512k 이상을 낼 수 없다. 그래서 리눅스 client 에서 인터넷을 연결시는 VPN 서버를 거치지 않게한 것이다. (외부에서 VPN 으로 받은 IP 주소로 리눅스 client 를 연결할 때는 당연히 VPN 서버를 거친다.) VPN 서버를 거치지 않으면 그 라인의 최고 속도를 다 이용할 수 있기 때문이다.
즉 리눅스 client 가 메일 서버이고 호스트 네임이 mail.pptp.co.kr 이라면 외부에서 mail.pptp.co.kr 로 메일을 보낼 때는 VPN 주소가 사용되지만 mail.pptp.co.kr 에서 다른 메일 서버로 메일을 보낼 때는 VPN 으로 받은 IP 주소가 아닌 리눅스 client나 공유기의 ADSL/케이블 라인의 IP 주소가 사용된다.
그러나 리눅스 client 에서 인터넷의 호스트를 연결하는데 그 호스트에서 상대방의 IP를 체크해서 특정 IP 만 연결을 허용한다면 리눅스 client 에서 데이타를 내 보낼때도 VPN IP로 나가야한다. 즉 VPN 서버를 거쳐야 한다.(이런 경우는 많지 않을 것이다.)
이 설정은 상당히 까다롭다. 왜냐하면 이렇게 하려면 리눅스 client의 default gateway 를 VPN Interface(ppp?) 로 변경해야하는데 이 때 단순히 게이트웨이를 변경하면 looping 이 발생한다.
물론 리눅스는 이 경우에도 당연히 설정이 가능하다. 여기서 방법을 설명하려면 복잡하므로 아래의 설정 프로그램을 다운받아 설치하면 자동으로 해결된다.
이 파일을 /etc/ppp 디렉터리에 넣고 tar xvf ip-dgw.tar 명령을 준다. ip-up 과 ip-down 두 파일이 나타난다.
즉 본문 "3" 번에서 설치된 /etc/ppp 디렉터리의 ip-up 파일을 새 파일로 대치하고 ip-down 파일을 하나 더 추가한 것이다. 다른 부분은 같다.
이젠 VPN을 연결하면 디폴트 게이트웨이가 VPN interface 로 변경될 것이다. 그리고 VPN 연결을 끊으면 연결 전의 라우팅 테이블로 복귀한다.
♣. VPN 연결 후의 라우팅 테이블은 아래와 같을 것이다. (리눅스 client 가 공유기 하단에 위치하고 192.168.1.x IP 주소를 사용하는 경우.)
bae@samba:~$ netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
220.230.5.3 0.0.0.0 255.255.255.255 UH 40 0 0 ppp0
192.168.1.0 0.0.0.0 255.255.255.0 U 40 0 0 eth0
127.0.0.0 0.0.0.0 255.0.0.0 U 40 0 0 lo
0.0.0.0 220.230.5.3 0.0.0.0 UG 40 0 0 ppp0
♣. 비대칭 라우팅을 사용하는 경우의 라우팅 테이블은 "[참고 3]" "1." 에 나와 있다.
[주의] ip-dgw.tar 를 설치하지 않고 디폴트 게이트웨이를 VPN 으로 변경하면 어떤 결과가 발생하는지 알고 싶으면 시험해 보십시오. 아마도 피시를 리부팅해야 할겁니다. VPN 연결만 끊는다고 해결되지 않습니다.
[버그] eth0 랜카드에 IP 주소가 두 개인 경우는 이 설정이 작동하지 않습니다. 리눅스랩으로 연락해서 수정 파일을 받아야 합니다.
[참고 2]
방화벽 내에서 ppTp VPN 연결
방화벽 내에서 사설 IP를 사용하는 경우에(NAT 방식 방화벽) 방화벽 내의 사설 IP를 사용하는 PC에서 ppTp VPN 을 연결하려면 방화벽에서 VPN 서버 주소(tiger 의 경우 220.230.5.5)로 부터의 ip protocol 47(GRE) 및 tcp source port 1723 번을 VPN을 연결하는 PC의 IP 주소로 port forwarding 해 주어야 한다. (방화벽의 DMZ 구간에 연결할 경우는 상관 없다.)
방화벽이 리눅스라면 아래 설정이 필요하다. (리눅스를 공유기로 사용하는 경우도 같다.)
방화벽의 인터넷 쪽 인터페이스가 eth1, IP 주소는 222.x.129.9, 방화벽의 랜 쪽 인터페이스가 eth0, IP 주소는 192.168.1.1 VPN 을 연결하는 리눅스 서버의 IP 주소가 192.168.1.7 이라면
리눅스 네트워킹을 아는 사람들은 왜 마지막 줄의 디폴트 게이트웨이가 ppp0 가 아니고 eth0 인지 의아해 할것이다. 이는 외부에서 리눅스의 VPN IP 로 연결은 가능하게하고 리눅스에서 다른 인터넷 사이트를 연결할 때는 ADSL/케이블 모뎀 IP 주소로 나가도록 policy routing 기법을 사용하기 때문이다.
[root@linuxlab] ifconfig
eth0 Link encap:Ethernet HWaddr 00:11:D8:52:0F:D4
inet addr:192.168.0.111 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
ppp0 Link encap:Point-to-Point Protocol
inet addr:59.150.255.xxx P-t-P:220.230.5.3 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
*. 화면 출력 중 불필요한 부분은 생략했다..
[Debian]
Debian 사용자라면 설명이 필요 없을 것 같다.
기타
위와 같이 구성하려면 공유기에 VPN(ppTp) Pass Through 기능이 있어야 한다. 그리고 공유기가 Multi-Session(multi port) 을 지원한다면 공유기에 연결된 다른 PC(192.168.0.2~3) 에서도 동시에 VPN 연결이 가능하다. 위의 경우에는 공유기의 랜 포트에 연결된 PC 에 IP 자동 부여(DHCP)를 사용해도 된다.
공유기에 VPN Pass Through 기능이 없으면 DMZ 를 사용해야 한다. 공유기에서 DMZ 를 설정하려면 공유기에 연결된 모든 PC(리눅스도 포함)의 IP를 수동으로 부여해야 한다. 그리고서 공유기에서 DMZ IP 주소를 리눅스 client 의 IP 주소로 지정한다.(DMZ를 사용한다면 한 대에서만 VPN 연결이 가능하다.)
정상적인 연결이 이루어 졌을 때의 client 쪽 /var/log/debug 파일 내용 (배포본에 따라서는 syslog, daemon.log 에 나올 수도 있다.)
*. /etc/ppp/options 에 debug 를 넣을 것.
Oct 10 15:15:40 samba pppd[25626]: using channel 8
Oct 10 15:15:41 samba pppd[25626]: sent [LCP ConfReq id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: rcvd [LCP ConfReq id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: sent [LCP ConfAck id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: rcvd [LCP ConfAck id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: sent [LCP EchoReq id=0x0 magic=0x4adeccad]
Oct 10 15:15:41 samba pppd[25626]: rcvd [LCP EchoReq id=0x0 magic=0x2dcd9a7b]
Oct 10 15:15:41 samba pppd[25626]: sent [LCP EchoRep id=0x0 magic=0x4adeccad]
Oct 10 15:15:41 samba pppd[25626]: rcvd [CHAP Challenge id=0x1 \
<98672bc235a6dee925c9c372ef5d073ec561a384>, name = "libra"]
Oct 10 15:15:41 samba pppd[25626]: sent [CHAP Response id=0x1 \
<13b202bcab861afd11bd91702c18e701>, name = "admin"]
Oct 10 15:15:41 samba pppd[25626]: rcvd [LCP EchoRep id=0x0 magic=0x2dcd9a7b]
Oct 10 15:15:41 samba pppd[25626]: rcvd [CHAP Success id=0x1 "Welcome to libra."]
Oct 10 15:15:41 samba pppd[25626]: sent [IPCP ConfReq id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: rcvd [IPCP ConfReq id=0x1 ]
Oct 10 15:15:41 samba pppd[25626]: sent [IPCP ConfAck id=0x1 ]
Oct 10 15:15:42 samba pppd[25626]: rcvd [IPCP ConfNak id=0x1 ]
Oct 10 15:15:42 samba pppd[25626]: sent [IPCP ConfReq id=0x2 ]
Oct 10 15:15:42 samba pppd[25626]: rcvd [IPCP ConfAck id=0x2 ]
Oct 10 15:15:42 samba pppd[25626]: Script /etc/ppp/ip-up started (pid 25630)
Oct 10 15:15:42 samba pppd[25626]: Script /etc/ppp/ip-up finished (pid 25630), status = 0x0
*. 마지막 줄의 "status = 0x0" 에서 0x0 대신 다른 코드가 나오면 debug 파일 내용과 사용 배포본, 커널 버전(uname -a), pptp 버전(pptp 명령을 준다.), pppd 버전 등을 메일(위의 메일 주소에서 _nospam 을 제거)로 보내 주십시오. 이 에러가 뜨면 VPN 을 연결해도 외부에서 VPN 으로 받은 IP로 접속이 안된다.
L4, QOS, Firewall, VPN 기능을 모두 갖춘 국내 유일의 L4 Switch Libra
In cryptography, modes of operation enable the repeated and secure use of a block cipher under a single key.[1][2] A block cipher by itself allows encryption only of a single data block of the cipher's block length. When targeting a variable-length message, the data must first be partitioned into separate cipher blocks. Typically, the last block must also be extended to match the cipher's block length using a suitable padding scheme. A mode of operation describes the process of encrypting each of these blocks, and generally uses randomization based on an additional input value, often called an initialization vector, to allow doing so safely.[1]
Modes of operation have primarily been defined for encryption and authentication.[1][3] Historically, encryption modes have been studied extensively in regard to their error propagation properties under various scenarios of data modification. Later development regarded integrity protection as an entirely separate cryptographic goal from encryption. Some modern modes of operation combine encryption and authentication in an efficient way, and are known as authenticated encryption modes.[2]
While modes of operation are commonly associated with symmetric encryption,[2] they may also be applied to public-key encryption primitives such as RSA in principle (though in practice public-key encryption of longer messages is generally realized using hybrid encryption).[1]
The earliest modes of operation, ECB, CBC, OFB, and CFB (see below for all), date back to 1981 and were specified in FIPS 81, DES Modes of Operation. In 2001, NIST revised its list of approved modes of operation by including AES as a block cipher and adding CTR mode in SP800-38A, Recommendation for Block Cipher Modes of Operation. Finally, in January, 2010, NIST added XTS-AES in SP800-38E, Recommendation for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on Storage Devices. Other confidentiality modes exist which have not been approved by NIST. For example, CTS is ciphertext stealing mode and available in many popular cryptographic libraries.
ECB, CBC, OFB, CFB, CTR, and XTS modes only provide confidentiality; to ensure an encrypted message is not accidentally modified or maliciously tampered requires a separatemessage authentication code such as CBC-MAC. The cryptographic community recognized the need for dedicated integrity assurances and NIST responded with HMAC, CMAC, and GMAC. HMAC was approved in 2002 as FIPS 198, The Keyed-Hash Message Authentication Code (HMAC), CMAC was released in 2005 under SP800-38B,Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication, and GMAC was formalized in 2007 under SP800-38D, Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC.
After observing that compositing a confidentiality mode with a authenticity mode could be difficult and error prone, the cryptographic community began to supply modes which combined confidentiality and authenticity into a single cryptographic primitive. The modes are referred to as authenticated encryption, AE, and authenc. Examples of authenc modes are CCM (SP800-38C), GCM (SP800-38D), CWC, EAX, IAPM, and OCB.
Modes of operation are nowadays defined by a number of national and internationally recognized standards bodies. The most influential source is the US NIST. Other notable standards organizations include the ISO, the IEC, the IEEE, the national ANSI, and the IETF.
An initialization vector (IV) is a block of bits that is used by several modes to randomize the encryption and hence to produce distinct ciphertexts even if the same plaintext is encrypted multiple times, without the need for a slower re-keying process.
An initialization vector has different security requirements than a key, so the IV usually does not need to be secret. However, in most cases, it is important that an initialization vector is never reused under the same key. For CBC and CFB, reusing an IV leaks some information about the first block of plaintext, and about any common prefix shared by the two messages. For OFB and CTR, reusing an IV completely destroys security. In CBC mode, the IV must, in addition, be unpredictable at encryption time; in particular, the (previously) common practice of re-using the last ciphertext block of a message as the IV for the next message is insecure (for example, this method was used by SSL 2.0). If an attacker knows the IV (or the previous block of ciphertext) before he specifies the next plaintext, he can check his guess about plaintext of some block that was encrypted with the same key before (this is known as the TLS CBC IV attack).[4]
A block cipher works on units of a fixed size (known as a block size), but messages come in a variety of lengths. So some modes (namely ECB and CBC) require that the final block be padded before encryption. Several padding schemes exist. The simplest is to add null bytes to the plaintext to bring its length up to a multiple of the block size, but care must be taken that the original length of the plaintext can be recovered; this is so, for example, if the plaintext is a C style string which contains no null bytes except at the end. Slightly more complex is the original DES method, which is to add a single one bit, followed by enough zero bits to fill out the block; if the message ends on a block boundary, a whole padding block will be added. Most sophisticated are CBC-specific schemes such as ciphertext stealing or residual block termination, which do not cause any extra ciphertext, at the expense of some additional complexity. Schneier and Ferguson suggest two possibilities, both simple: append a byte with value 128 (hex 80), followed by as many zero bytes as needed to fill the last block, or pad the last block with n bytes all with value n.
CFB, OFB and CTR modes do not require any special measures to handle messages whose lengths are not multiples of the block size, since the modes work by XORing the plaintext with the output of the block cipher. The last partial block of plaintext is XORed with the first few bytes of the last keystream block, producing a final ciphertext block that is the same size as the final partial plaintext block. This characteristic of stream ciphers makes them suitable for applications that require the encrypted ciphertext data to be the same size as the original plaintext data, and for applications that transmit data in streaming form where it is inconvenient to add padding bytes.
The simplest of the encryption modes is the electronic codebook (ECB) mode. The message is divided into blocks and each block is encrypted separately.
The disadvantage of this method is that identical plaintext blocks are encrypted into identical ciphertext blocks; thus, it does not hide data patterns well. In some senses, it doesn't provide serious message confidentiality, and it is not recommended for use in cryptographic protocols at all. A striking example of the degree to which ECB can leave plaintext data patterns in the ciphertext is shown below; a pixel-map version of the image on the left was encrypted with ECB mode to create the center image, versus a non-ECB mode for the right image.
Original
Encrypted using ECB mode
Modes other than ECB result in pseudo-randomness
The image on the right is how the image might appear encrypted with CBC, CTR or any of the other more secure modes—indistinguishable from random noise. Note that the random appearance of the image on the right does not indicate whether the image has been securely encrypted; many kinds of insecure encryption have been developed which would produce output just as 'random-looking'.
ECB mode can also make protocols without integrity protection even more susceptible to replay attacks, since each block gets decrypted in exactly the same way. For example, the Phantasy Star Online: Blue Burst online video game uses Blowfish in ECB mode. Before the key exchange system was cracked leading to even easier methods, cheaters repeated encrypted "monster killed" message packets, each an encrypted Blowfish block, to illegitimately gain experience points quickly.[citation needed]
CBC mode of operation was invented by IBM in 1976.[5] In the cipher-block chaining (CBC) mode, each block of plaintext is XORed with the previous ciphertext block before being encrypted. This way, each ciphertext block is dependent on all plaintext blocks processed up to that point. Also, to make each message unique, an initialization vector must be used in the first block.
If the first block has index 1, the mathematical formula for CBC encryption is
while the mathematical formula for CBC decryption is
CBC has been the most commonly used mode of operation. Its main drawbacks are that encryption is sequential (i.e., it cannot be parallelized), and that the message must be padded to a multiple of the cipher block size. One way to handle this last issue is through the method known as ciphertext stealing.
Note that a one-bit change in a plaintext affects all following ciphertext blocks. A plaintext can be recovered from just two adjacent blocks of ciphertext. As a consequence, decryption can be parallelized, and a one-bit change to the ciphertext causes complete corruption of the corresponding block of plaintext, and inverts the corresponding bit in the following block of plaintext.
The propagating cipher-block chaining or plaintext cipher-block chaining[6] mode was designed to cause small changes in the ciphertext to propagate indefinitely when decrypting, as well as when encrypting.
Encryption and decryption algorithms are as follows:
PCBC is used in Kerberos v4 and WASTE, most notably, but otherwise is not common. On a message encrypted in PCBC mode, if two adjacent ciphertext blocks are exchanged, this does not affect the decryption of subsequent blocks[7]. For this reason, PCBC is not used in Kerberos v5.
The cipher feedback (CFB) mode, a close relative of CBC, makes a block cipher into a self-synchronizing stream cipher. Operation is very similar; in particular, CFB decryption is almost identical to CBC encryption performed in reverse:
This simplest way of using CFB described above is not any more self-synchronizing than other cipher modes like CBC. If a whole blocksize of ciphertext is lost both CBC and CFB will synchronize, but losing only a single byte or bit will permanently throw off decryption. To be able to synchronize after the loss of only a single byte or bit, a single byte or bit must be encrypted at a time. CFB can be used this way when combined with a shift register as the input for the block cipher.
To use CFB to make a self-synchronizing stream cipher that will synchronize for any multiple of x bits lost, start by initializing a shift register the size of the block size with the initialization vector. This is encrypted with the block cipher, and the highest x bits of the result are XOR'ed with x bits of the plaintext to produce x bits of ciphertext. These x bits of output are shifted into the shift register, and the process repeats with the next x bits of plaintext. Decryption is similar, start with the initialization vector, encrypt, and XOR the high bits of the result with x bits of the ciphertext to produce x bits of plaintext. Then shift the x bits of the ciphertext into the shift register.
In notation, where Si is the ith state of the shift register, a << x is a shifted up x bits, head(a, x) is the x highest bits of a and n is number of bits of IV:
If x bits are lost from the ciphertext, the cipher will output incorrect plaintext until the shift register once again equals a state it held while encrypting, at which point the cipher has resynchronized. This will result in at most one blocksize of output being garbled.
Like CBC mode, changes in the plaintext propagate forever in the ciphertext, and encryption cannot be parallelized. Also like CBC, decryption can be parallelized. When decrypting, a one-bit change in the ciphertext affects two plaintext blocks: a one-bit change in the corresponding plaintext block, and complete corruption of the following plaintext block. Later plaintext blocks are decrypted normally.
CFB shares two advantages over CBC mode with the stream cipher modes OFB and CTR: the block cipher is only ever used in the encrypting direction, and the message does not need to be padded to a multiple of the cipher block size (though ciphertext stealing can also be used to make padding unnecessary).
The output feedback (OFB) mode makes a block cipher into a synchronous stream cipher. It generates keystream blocks, which are then XORed with the plaintext blocks to get the ciphertext. Just as with other stream ciphers, flipping a bit in the ciphertext produces a flipped bit in the plaintext at the same location. This property allows many error correcting codes to function normally even when applied before encryption.
Because of the symmetry of the XOR operation, encryption and decryption are exactly the same:
Each output feedback block cipher operation depends on all previous ones, and so cannot be performed in parallel. However, because the plaintext or ciphertext is only used for the final XOR, the block cipher operations may be performed in advance, allowing the final step to be performed in parallel once the plaintext or ciphertext is available.
It is possible to obtain an OFB mode keystream by using CBC mode with a constant string of zeroes as input. This can be useful, because it allows the usage of fast hardware implementations of CBC mode for OFB mode encryption.
Using OFB mode with a partial block as feedback like CFB mode reduces the average cycle length by a factor of 232 or more. A mathematical model proposed by Davies and Parkin and substantiated by experimental results showed that only with full feedback an average cycle length near to the obtainable maximum can be achieved. For this reason, support for truncated feedback was removed from the specification of OFB.[8][9]
Note: CTR mode (CM) is also known as Integer Counter Mode (ICM) and Segmented Integer Counter (SIC) mode
Like OFB, counter mode turns a block cipher into a stream cipher. It generates the next keystream block by encrypting successive values of a "counter". The counter can be any function which produces a sequence which is guaranteed not to repeat for a long time, although an actual counter is the simplest and most popular. The usage of a simple deterministic input function used to be controversial; critics argued that "deliberately exposing a cryptosystem to a known systematic input represents an unnecessary risk."[10]By now, CTR mode is widely accepted, and problems resulting from the input function are recognized as a weakness of the underlying block cipher instead of the CTR mode.[11]Nevertheless, there are specialized attacks like a Hardware Fault Attack that is based on the usage of a simple counter function as input.[12]
CTR mode has similar characteristics to OFB, but also allows a random access property during decryption. CTR mode is well suited to operation on a multi-processor machine where blocks can be encrypted in parallel.
Note that the nonce in this graph is the same thing as the initialization vector (IV) in the other graphs. The IV/nonce and the counter can be concatenated, added, or XORed together to produce the actual unique counter block for encryption.
Before the wide spread use of message authentication codes and authenticated encryption, it was common to discuss the "error propagation" properties as a selection criterion for a mode of operation. It might be observed, for example, that a one-block error in the transmitted ciphertext would result in a one-block error in the reconstructed plaintext forECB mode encryption, while in CBC mode such an error would affect two blocks.
Some felt that such resilience was desirable in the face of random errors (eg, line noise), while others argued that error correcting increased the scope for attackers to maliciously tamper with a message.
However, when proper integrity protection is used, such an error will result (with high probability) in the entire message being rejected. If resistance to random error is desirable,error-correcting codes should be applied to the ciphertext before transmission.
A number of modes of operation have been designed to combine confidentiality and authentication in a single cryptographic primitive. Examples of such modes are XCBC[13],IACBC, IAPM[14], OCB, EAX, CWC, CCM, and GCM. Authenticated encryption modes are classified as single pass modes or double pass modes. Unfortunately for the cryptographic user community, many of the single pass authenticated encryption algorithms (such as OCB mode) are patent encumbered.
In addition, some modes also allow for the authentication of unencrypted associated data, and these are called AEAD (Authenticated-Encryption with Associated-Data) schemes. For example, EAX mode is a double pass AEAD scheme while OCB mode is single pass.
[edit]Other modes and other cryptographic primitives
Many more modes of operation for block ciphers have been suggested. Some have been accepted, fully described (even standardized), and are in use. Others have been found insecure, and should never be used. Still others don't categorize as confidentiality, authenticity, or authenticated encryption - for example Key Feedback Mode (KFM) and AES-hash.
Disk encryption often uses special purpose modes specifically designed for the application. Tweakable narrow-block encryption modes (LRW, XEX, and XTS) and wide-block encryption modes (CMC and EME) are designed to securely encrypt sectors of a disk. (See disk encryption theory)
Block ciphers can also be used in other cryptographic protocols. They are generally used in modes of operation similar to the block modes described here. As with all protocols, to be cryptographically secure, care must be taken to build them correctly.
^ William F. Ehrsam, Carl H. W. Meyer, John L. Smith, Walter L. Tuchman, "Message verification and transmission error detection by block chaining", US Patent 4074066, 1976
^ Kaufman, C., Perlman, R., & Speciner, M (2002). Network Security. Upper Saddle River, NJ: Prentice Hall. Page 319 (2nd Ed.)
^ D. W. Davies and G. I. P. Parkin. The average cycle size of the key stream in output feedback encipherment. In Advances in Cryptology, Proceedings of CRYPTO 82, pages 263–282, 1982
^ Robert R. Jueneman. Analysis of certain aspects of output feedback mode. In Advances in Cryptology, Proceedings of CRYPTO 82, pages 99–127, 1982.
^ Helger Lipmaa, Phillip Rogaway, and David Wagner. Comments to NIST concerning AES modes of operation: CTR-mode encryption. 2000
^ R. Tirtea and G. Deconinck. Specifications overview for counter mode of operation. security aspects in case of faults. In Electrotechnical Conference, 2004. MELECON 2004. Proceedings of the 12th IEEE Mediterranean, pages 769–773 Vol.2, 2004.
^ Virgil D. Gligor, Pompiliu Donescu, "Fast Encryption and Authentication: XCBC Encryption and XECB Authentication Modes". Proc. Fast Software Encryption, 2001: 92-108.
^ Charanjit S. Jutla, "Encryption Modes with Almost Free Message Integrity", Proc. Eurocrypt 2001, LNCS 2045, May 2001.
Network Address Translation (NAT) causes well-known difficulties for peer-to-peer (P2P) communication, since the peers involved may not be reachable at any globally valid IP address. Several NAT traversal techniques are known, but their documentation is slim, and data about their robustness or relative merits is slimmer. This paper documents and analyzes one of the simplest but most robust and practical NAT traversal techniques, commonly known as “hole punching.” Hole punching is moderately well-understood for UDP communication, but we show how it can be reliably used to set up peer-to-peer TCP streams as well. After gathering data on the reliability of this technique on a wide variety of deployed NATs, we find that about 82% of the NATs tested support hole punching for UDP, and about 64% support hole punching for TCP streams. As NAT vendors become increasingly conscious of the needs of important P2P applications such as Voice over IP and online gaming protocols, support for hole punching is likely to increase in the future.
1 Introduction
The combined pressures of tremendous growth and massive security challenges have forced the Internet to evolve in ways that make life difficult for many applications. The Internet's original uniform address architecture, in which every node has a globally unique IP address and can communicate directly with every other node, has been replaced with a new de facto Internet address architecture, consisting of a global address realm and many private address realms interconnected by Network Address Translators (NAT). In this new address architecture, illustrated in Figure 1, only nodes in the “main,” global address realm can be easily contacted from anywhere in the network, because only they have unique, globally routable IP addresses. Nodes on private networks can connect to other nodes on the same private network, and they can usually open TCP or UDP connections to “well-known” nodes in the global address realm. NATs on the path allocate temporary public endpoints for outgoing connections, and translate the addresses and port numbers in packets comprising those sessions, while generally blocking all incoming traffic unless otherwise specifically configured.
Figure 1: Public and private IP address domains
The Internet's new de facto address architecture is suitable for client/server communication in the typical case when the client is on a private network and the server is in the global address realm. The architecture makes it difficult for two nodes on different private networks to contact each other directly, however, which is often important to the “peer-to-peer” communication protocols used in applications such as teleconferencing and online gaming. We clearly need a way to make such protocols function smoothly in the presence of NAT.
One of the most effective methods of establishing peer-to-peer communication between hosts on different private networks is known as “hole punching.” This technique is widely used already in UDP-based applications, but essentially the same technique also works for TCP. Contrary to what its name may suggest, hole punching does not compromise the security of a private network. Instead, hole punching enables applications to function within the the default security policy of most NATs, effectively signaling to NATs on the path that peer-to-peer communication sessions are “solicited” and thus should be accepted. This paper documents hole punching for both UDP and TCP, and details the crucial aspects of both application and NAT behavior that make hole punching work.
Unfortunately, no traversal technique works with all existing NATs, because NAT behavior is not standardized. This paper presents some experimental results evaluating hole punching support in current NATs. Our data is derived from results submitted by users throughout the Internet by running our “NAT Check” tool over a wide variety of NATs by different vendors. While the data points were gathered from a “self-selecting” user community and may not be representative of the true distribution of NAT implementations deployed on the Internet, the results are nevertheless generally encouraging.
While evaluating basic hole punching, we also point out variations that can make hole punching work on a wider variety of existing NATs at the cost of greater complexity. Our primary focus, however, is on developing the simplest hole punching technique that works cleanly and robustly in the presence of “well-behaved” NATs in any reasonable network topology. We deliberately avoid excessively clever tricks that may increase compatibility with some existing “broken” NATs in the short term, but which only work some of the time and may cause additional unpredictability and network brittleness in the long term.
Although the larger address space of IPv6 [3] may eventually reduce the need for NAT, in the short term IPv6 is increasing the demand for NAT, because NAT itself provides the easiest way to achieve interoperability between IPv4 and IPv6 address domains [24]. Further, the anonymity and inaccessibility of hosts on private networks has widely perceived security and privacy benefits. Firewalls are unlikely to go away even when there are enough IP addresses: IPv6 firewalls will still commonly block unsolicited incoming traffic by default, making hole punching useful even to IPv6 applications.
The rest of this paper is organized as follows. Section 2 introduces basic terminology and NAT traversal concepts. Section 3 details hole punching for UDP, and Section 4 introduces hole punching for TCP. Section 5 summarizes important properties a NAT must have in order to enable hole punching. Section 6 presents our experimental results on hole punching support in popular NATs, Section 7 discusses related work, and Section 8concludes.
2 General Concepts
This section introduces basic NAT terminology used throughout the paper, and then outlines general NAT traversal techniques that apply equally to TCP and UDP.
This paper adopts the NAT terminology and taxonomy defined in RFC 2663 [21], as well as additional terms defined more recently in RFC 3489 [19].
Of particular importance is the notion of session. A session endpoint for TCP or UDP is an (IP address, port number) pair, and a particular sessionis uniquely identified by its two session endpoints. From the perspective of one of the hosts involved, a session is effectively identified by the 4-tuple (local IP, local port, remote IP, remote port). The direction of a session is normally the flow direction of the packet that initiates the session: the initial SYN packet for TCP, or the first user datagram for UDP.
Of the various flavors of NAT, the most common type is traditional or outbound NAT, which provides an asymmetric bridge between a private network and a public network. Outbound NAT by default allows only outbound sessions to traverse the NAT: incoming packets are dropped unless the NAT identifies them as being part of an existing session initiated from within the private network. Outbound NAT conflicts with peer-to-peer protocols because when both peers desiring to communicate are “behind” (on the private network side of) two different NATs, whichever peer tries to initiate a session, the other peer's NAT rejects it. NAT traversal entails making P2P sessions look like “outbound” sessions to both NATs.
Outbound NAT has two sub-varieties: Basic NAT, which only translates IP addresses, and Network Address/Port Translation (NAPT), which translates entire session endpoints. NAPT, the more general variety, has also become the most common because it enables the hosts on a private network to share the use of a single public IP address. Throughout this paper we assume NAPT, though the principles and techniques we discuss apply equally well (if sometimes trivially) to Basic NAT.
The most reliable--but least efficient--method of P2P communication across NAT is simply to make the communication look to the network like standard client/server communication, through relaying. Suppose two client hosts and have each initiated TCP or UDP connections to a well-known server , at 's global IP address 18.181.0.31 and port number 1234. As shown in Figure 2, the clients reside on separate private networks, and their respective NATs prevent either client from directly initiating a connection to the other. Instead of attempting a direct connection, the two clients can simply use the server to relay messages between them. For example, to send a message to client , client simply sends the message to server along its already-established client/server connection, and server forwards the message on to client using its existing client/server connection with .
Figure 2: NAT Traversal by Relaying
Relaying always works as long as both clients can connect to the server. Its disadvantages are that it consumes the server's processing power and network bandwidth, and communication latency between the peering clients is likely increased even if the server is well-connected. Nevertheless, since there is no more efficient technique that works reliably on all existing NATs, relaying is a useful fall-back strategy if maximum robustness is desired. The TURN protocol [18] defines a method of implementing relaying in a relatively secure fashion.
Some P2P applications use a straightforward but limited technique, known as connection reversal, to enable communication when both hosts have connections to a well-known rendezvous server and only one of the peers is behind a NAT, as shown in Figure 3. If wants to initiate a connection to , then a direct connection attempt works automatically, because is not behind a NAT and 's NAT interprets the connection as an outgoing session. If wants to initiate a connection to , however, any direct connection attempt to is blocked by 's NAT. can instead relay a connection request to through a well-known server , asking to attempt a “reverse” connection back to . Despite the obvious limitations of this technique, the central idea of using a well-known rendezvous server as an intermediary to help set up direct peer-to-peer connections is fundamental to the more general hole punching techniques described next.
Figure 3: NAT Traversal by Connection Reversal
3 UDP Hole Punching
UDP hole punching enables two clients to set up a direct peer-to-peer UDP session with the help of a well-known rendezvous server, even if the clients are both behind NATs. This technique was mentioned in section 5.1 of RFC 3027 [10], documented more thoroughly elsewhere on the Web [13], and used in recent experimental Internet protocols [17,11]. Various proprietary protocols, such as those for on-line gaming, also use UDP hole punching.
Hole punching assumes that the two clients, and , already have active UDP sessions with a rendezvous server . When a client registers with , the server records two endpoints for that client: the (IP address, UDP port) pair that the client believes itself to be using to talk with , and the (IP address, UDP port) pair that the server observes the client to be using to talk with it. We refer to the first pair as the client's private endpoint and the second as the client's public endpoint. The server might obtain the client's private endpoint from the client itself in a field in the body of the client's registration message, and obtain the client's public endpoint from the source IP address and source UDP port fields in the IP and UDP headers of that registration message. If the client is not behind a NAT, then its private and public endpoints should be identical.
A few poorly behaved NATs are known to scan the body of UDP datagrams for 4-byte fields that look like IP addresses, and translate them as they would the IP address fields in the IP header. To be robust against such behavior, applications may wish to obfuscate IP addresses in messages bodies slightly, for example by transmitting the one's complement of the IP address instead of the IP address itself. Of course, if the application is encrypting its messages, then this behavior is not likely to be a problem.
Suppose client wants to establish a UDP session directly with client . Hole punching proceeds as follows:
initially does not know how to reach , so asks for help establishing a UDP session with .
replies to with a message containing 's public and private endpoints. At the same time, uses its UDP session with to send a connection request message containing 's public and private endpoints. Once these messages are received, and know each other's public and private endpoints.
When receives 's public and private endpoints from , starts sending UDP packets to both of these endpoints, and subsequently “locks in” whichever endpoint first elicits a valid response from . Similarly, when receives 's public and private endpoints in the forwarded connection request, starts sending UDP packets to at each of 's known endpoints, locking in the first endpoint that works. The order and timing of these messages are not critical as long as they are asynchronous.
We now consider how UDP hole punching handles each of three specific network scenarios. In the first situation, representing the “easy” case, the two clients actually reside behind the same NAT, on one private network. In the second, most common case, the clients reside behind different NATs. In the third scenario, the clients each reside behind two levels of NAT: a common “first-level” NAT deployed by an ISP for example, and distinct “second-level” NATs such as consumer NAT routers for home networks.
It is in general difficult or impossible for the application itself to determine the exact physical layout of the network, and thus which of these scenarios (or the many other possible ones) actually applies at a given time. Protocols such as STUN [19] can provide some information about the NATs present on a communication path, but this information may not always be complete or reliable, especially when multiple levels of NAT are involved. Nevertheless, hole punching works automatically in all of these scenarios without the application having to know the specific network organization, as long as the NATs involved behave in a reasonable fashion. (“Reasonable” behavior for NATs will be described later in Section 5.)
First consider the simple scenario in which the two clients (probably unknowingly) happen to reside behind the same NAT, and are therefore located in the same private IP address realm, as shown in Figure 4. Client has established a UDP session with server , to which the common NAT has assigned its own public port number 62000. Client has similarly established a session with , to which the NAT has assigned public port number 62005.
Figure 4: UDP Hole Punching, Peers Behind a Common NAT
Suppose that client uses the hole punching technique outlined above to establish a UDP session with , using server as an introducer. Client sends a message requesting a connection to . responds to with 's public and private endpoints, and also forwards 's public and private endpoints to . Both clients then attempt to send UDP datagrams to each other directly at each of these endpoints. The messages directed to the public endpoints may or may not reach their destination, depending on whether or not the NAT supports hairpin translation as described below in Section 3.5. The messages directed at the private endpoints do reach their destinations, however, and since this direct route through the private network is likely to be faster than an indirect route through the NAT anyway, the clients are most likely to select the private endpoints for subsequent regular communication.
By assuming that NATs support hairpin translation, the application might dispense with the complexity of trying private as well as public endpoints, at the cost of making local communication behind a common NAT unnecessarily pass through the NAT. As our results in Section 6 show, however, hairpin translation is still much less common among existing NATs than are other “P2P-friendly” NAT behaviors. For now, therefore, applications may benefit substantially by using both public and private endpoints.
Suppose clients and have private IP addresses behind different NATs, as shown in Figure 5. and have each initiated UDP communication sessions from their local port 4321 to port 1234 on server . In handling these outbound sessions, NAT has assigned port 62000 at its own public IP address, 155.99.25.11, for the use of 's session with , and NAT has assigned port 31000 at its IP address, 138.76.29.7, to 's session with .
Figure 5: UDP Hole Punching, Peers Behind Different NATs
In 's registration message to , reports its private endpoint to as 10.0.0.1:4321, where 10.0.0.1 is 's IP address on its own private network. records 's reported private endpoint, along with 's public endpoint as observed by itself. 's public endpoint in this case is 155.99.25.11:62000, the temporary endpoint assigned to the session by the NAT. Similarly, when client registers, records 's private endpoint as 10.1.1.3:4321 and 's public endpoint as 138.76.29.7:31000.
Now client follows the hole punching procedure described above to establish a UDP communication session directly with . First, sends a request message to asking for help connecting with . In response, sends 's public and private endpoints to , and sends 's public and private endpoints to . and each start trying to send UDP datagrams directly to each of these endpoints.
Since and are on different private networks and their respective private IP addresses are not globally routable, the messages sent to these endpoints will reach either the wrong host or no host at all. Because many NATs also act as DHCP servers, handing out IP addresses in a fairly deterministic way from a private address pool usually determined by the NAT vendor by default, it is quite likely in practice that 's messages directed at 's private endpoint will reach some (incorrect) host on 's private network that happens to have the same private IP address as does. Applications must therefore authenticate all messages in some way to filter out such stray traffic robustly. The messages might include application-specific names or cryptographic tokens, for example, or at least a random nonce pre-arranged through .
Now consider 's first message sent to 's public endpoint, as shown in Figure 5. As this outbound message passes through 's NAT, this NAT notices that this is the first UDP packet in a new outgoing session. The new session's source endpoint (10.0.0.1:4321) is the same as that of the existing session between and , but its destination endpoint is different. If NAT is well-behaved, it preserves the identity of 's private endpoint, consistently translating all outbound sessions from private source endpoint 10.0.0.1:4321 to the corresponding public source endpoint 155.99.25.11:62000. 's first outgoing message to 's public endpoint thus, in effect, “punches a hole” in 's NAT for a new UDP session identified by the endpoints (10.0.0.1:4321, 138.76.29.7:31000) on 's private network, and by the endpoints (155.99.25.11:62000, 138.76.29.7:31000) on the main Internet.
If 's message to 's public endpoint reaches 's NAT before 's first message to has crossed 's own NAT, then 's NAT may interpret 's inbound message as unsolicited incoming traffic and drop it. 's first message to 's public address, however, similarly opens a hole in 's NAT, for a new UDP session identified by the endpoints (10.1.1.3:4321, 155.99.25.11:62000) on 's private network, and by the endpoints (138.76.29.7:31000, 155.99.25.11:62000) on the Internet. Once the first messages from and have crossed their respective NATs, holes are open in each direction and UDP communication can proceed normally. Once the clients have verified that the public endpoints work, they can stop sending messages to the alternative private endpoints.
3.5 Peers Behind Multiple Levels of NAT
In some topologies involving multiple NAT devices, two clients cannot establish an “optimal” P2P route between them without specific knowledge of the topology. Consider a final scenario, depicted in Figure 6. Suppose NAT is a large industrial NAT deployed by an internet service provider (ISP) to multiplex many customers onto a few public IP addresses, and NATs and are small consumer NAT routers deployed independently by two of the ISP's customers to multiplex their private home networks onto their respective ISP-provided IP addresses. Only server and NAT have globally routable IP addresses; the “public” IP addresses used by NAT and NAT are actually private to the ISP's address realm, while client 's and 's addresses in turn are private to the addressing realms of NAT and NAT , respectively. Each client initiates an outgoing connection to server as before, causing NATs and each to create a single public/private translation, and causing NAT to establish a public/private translation for each session.
Now suppose and attempt to establish a direct peer-to-peer UDP connection via hole punching. The optimal routing strategy would be for client to send messages to client 's “semi-public” endpoint at NAT , 10.0.1.2:55000 in the ISP's addressing realm, and for client to send messages to 's “semi-public” endpoint at NAT , namely 10.0.1.1:45000. Unfortunately, and have no way to learn these addresses, because server only sees the truly global public endpoints of the clients, 155.99.25.11:62000 and 155.99.25.11:62005 respectively. Even if and had some way to learn these addresses, there is still no guarantee that they would be usable, because the address assignments in the ISP's private address realm might conflict with unrelated address assignments in the clients' private realms. (NAT 's IP address in NAT 's realm might just as easily have been 10.1.1.3, for example, the same as client 's private address in NAT 's realm.)
The clients therefore have no choice but to use their global public addresses as seen by for their P2P communication, and rely on NAT providing hairpin or loopback translation. When sends a UDP datagram to 's global endpoint, 155.99.25.11:62005, NAT first translates the datagram's source endpoint from 10.0.0.1:4321 to 10.0.1.1:45000. The datagram now reaches NAT , which recognizes that the datagram's destination address is one of NAT 's own translated public endpoints. If NAT is well-behaved, it then translates both the source and destination addresses in the datagram and “loops” the datagram back onto the private network, now with a source endpoint of 155.99.25.11:62000 and a destination endpoint of 10.0.1.2:55000. NAT finally translates the datagram's destination address as the datagram enters 's private network, and the datagram reaches . The path back to works similarly. Many NATs do not yet support hairpin translation, but it is becoming more common as NAT vendors become aware of this issue.
Since the UDP transport protocol provides NATs with no reliable, application-independent way to determine the lifetime of a session crossing the NAT, most NATs simply associate an idle timer with UDP translations, closing the hole if no traffic has used it for some time period. There is unfortunately no standard value for this timer: some NATs have timeouts as short as 20 seconds. If the application needs to keep an idle UDP session active after establishing the session via hole punching, the application must send periodic keep-alive packets to ensure that the relevant translation state in the NATs does not disappear.
Unfortunately, many NATs associate UDP idle timers with individual UDP sessions defined by a particular pair of endpoints, so sending keep-alives on one session will not keep other sessions active even if all the sessions originate from the same private endpoint. Instead of sending keep-alives on many different P2P sessions, applications can avoid excessive keep-alive traffic by detecting when a UDP session no longer works, and re-running the original hole punching procedure again “on demand.”
4 TCP Hole Punching
Establishing peer-to-peer TCP connections between hosts behind NATs is slightly more complex than for UDP, but TCP hole punching is remarkably similar at the protocol level. Since it is not as well-understood, it is currently supported by fewer existing NATs. When the NATs involved do support it, however, TCP hole punching is just as fast and reliable as UDP hole punching. Peer-to-peer TCP communication across well-behaved NATs may in fact be more robust than UDP communication, because unlike UDP, the TCP protocol's state machine gives NATs on the path a standard way to determine the precise lifetime of a particular TCP session.
The main practical challenge to applications wishing to implement TCP hole punching is not a protocol issue but an application programming interface (API) issue. Because the standard Berkeley sockets API was designed around the client/server paradigm, the API allows a TCP stream socket to be used to initiate an outgoing connection via connect(), or to listen for incoming connections via listen() and accept(), but not both. Further, TCP sockets usually have a one-to-one correspondence to TCP port numbers on the local host: after the application binds one socket to a particular local TCP port, attempts to bind a second socket to the same TCP port fail.
For TCP hole punching to work, however, we need to use a single local TCP port to listen for incoming TCP connections and to initiate multiple outgoing TCP connections concurrently. Fortunately, all major operating systems support a special TCP socket option, commonly namedSO_REUSEADDR, which allows the application to bind multiple sockets to the same local endpoint as long as this option is set on all of the sockets involved. BSD systems have introduced a SO_REUSEPORT option that controls port reuse separately from address reuse; on such systems both of these options must be set.
4.2 Opening Peer-to-Peer TCP Streams
Suppose that client wishes to set up a TCP connection with client . We assume as usual that both and already have active TCP connections with a well-known rendezvous server . The server records each registered client's public and private endpoints, just as for UDP. At the protocol level, TCP hole punching works almost exactly as for UDP:
Client uses its active TCP session with to ask for help connecting to .
replies to with 's public and private TCP endpoints, and at the same time sends 's public and private endpoints to .
From the same local TCP ports that and used to register with , and each asynchronously make outgoing connection attempts to the other's public and private endpoints as reported by , while simultaneously listening for incoming connections on their respective local TCP ports.
and wait for outgoing connection attempts to succeed, and/or for incoming connections to appear. If one of the outgoing connection attempts fails due to a network error such as “connection reset” or “host unreachable,” the host simply re-tries that connection attempt after a short delay (e.g., one second), up to an application-defind maximum timeout period.
When a TCP connection is made, the hosts authenticate each other to verify that they connected to the intended host. If authentication fails, the clients close that connection and continue waiting for others to succeed. The clients use the first successfully authenticated TCP stream resulting from this process.
Unlike with UDP, where each client only needs one socket to communicate with both and any number of peers simultaneously, with TCP each client application must manage several sockets bound to a single local TCP port on that client node, as shown in Figure 7. Each client needs a stream socket representing its connection to , a listen socket on which to accept incoming connections from peers, and at least two additional stream sockets with which to initiate outgoing connections to the other peer's public and private TCP endpoints.
Figure 7: Sockets versus Ports for TCP Hole Punching
Consider the common-case scenario in which the clients and are behind different NATs, as shown in Figure 5, and assume that the port numbers shown in the figure are now for TCP rather than UDP ports. The outgoing connection attempts and make to each other's private endpoints either fail or connect to the wrong host. As with UDP, it is important that TCP applications authenticate their peer-to-peer sessions, due of the likelihood of mistakenly connecting to a random host on the local network that happens to have the same private IP address as the desired host on a remote private network.
The clients' outgoing connection attempts to each other's public endpoints, however, cause the respective NATs to open up new “holes” enabling direct TCP communication between and . If the NATs are well-behaved, then a new peer-to-peer TCP stream automatically forms between them. If 's first SYN packet to reaches 's NAT before 's first SYN packet to reaches 's NAT, for example, then 's NAT may interpret 's SYN as an unsolicited incoming connection attempt and drop it. 's first SYN packet to should subsequently get through, however, because's NAT sees this SYN as being part of the outbound session to that 's first SYN had already initiated.
What the client applications observe to happen with their sockets during TCP hole punching depends on the timing and the TCP implementations involved. Suppose that 's first outbound SYN packet to 's public endpoint is dropped by NAT , but 's first subsequent SYN packet to 's public endpoint gets through to before 's TCP retransmits its SYN. Depending on the operating system involved, one of two things may happen:
's TCP implementation notices that the session endpoints for the incoming SYN match those of an outbound session was attempting to initiate. 's TCP stack therefore associates this new session with the socket that the local application on was using to connect() to 's public endpoint. The application's asynchronous connect() call succeeds, and nothing happens with the application's listen socket.
Since the received SYN packet did not include an ACK for 's previous outbound SYN, 's TCP replies to 's public endpoint with a SYN-ACK packet, the SYN part being merely a replay of 's original outbound SYN, using the same sequence number. Once 's TCP receives 's SYN-ACK, it responds with its own ACK for 's SYN, and the TCP session enters the connected state on both ends.
Alternatively, 's TCP implementation might instead notice that has an active listen socket on that port waiting for incoming connection attempts. Since 's SYN looks like an incoming connection attempt, 's TCP creates a new stream socket with which to associate the new TCP session, and hands this new socket to the application via the application's next accept() call on its listen socket. 's TCP then responds to with a SYN-ACK as above, and TCP connection setup proceeds as usual for client/server-style connections.
Since 's prior outbound connect() attempt to used a combination of source and destination endpoints that is now in use by another socket, namely the one just returned to the application via accept(), 's asynchronous connect() attempt must fail at some point, typically with an “address in use” error. The application nevertheless has the working peer-to-peer stream socket it needs to communicate with , so it ignores this failure.
The first behavior above appears to be usual for BSD-based operating systems, whereas the second behavior appears more common under Linux and Windows.
4.4 Simultaneous TCP Open
Suppose that the timing of the various connection attempts during the hole punching process works out so that the initial outgoing SYN packets from both clients traverse their respective local NATs, opening new outbound TCP sessions in each NAT, before reaching the remote NAT. In this “lucky” case, the NATs do not reject either of the initial SYN packets, and the SYNs cross on the wire between the two NATs. In this case, the clients observe an event known as a simultaneous TCP open: each peer's TCP receives a “raw” SYN while waiting for a SYN-ACK. Each peer's TCP responds with a SYN-ACK, whose SYN part essentially “replays” the peer's previous outgoing SYN, and whose ACK part acknowledges the SYN received from the other peer.
What the respective applications observe in this case again depends on the behavior of the TCP implementations involved, as described in the previous section. If both clients implement the second behavior above, it may be that all of the asynchronous connect() calls made by the application ultimately fail, but the application running on each client nevertheless receives a new, working peer-to-peer TCP stream socket viaaccept()--as if this TCP stream had magically “created itself” on the wire and was merely passively accepted at the endpoints! As long as the application does not care whether it ultimately receives its peer-to-peer TCP sockets via connect() or accept(), the process results in a working stream on any TCP implementation that properly implements the standard TCP state machine specified in RFC 793 [23].
Each of the alternative network organization scenarios discussed in Section 3 for UDP works in exactly the same way for TCP. For example, TCP hole punching works in multi-level NAT scenarios such as the one in Figure 6 as long as the NATs involved are well-behaved.
4.5 Sequential Hole Punching
In a variant of the above TCP hole punching procedure implemented by the NatTrav library [4], the clients attempt connections to each other sequentially rather than in parallel. For example: (1) informs via of its desire to communicate, without simultaneously listening on its local port; (2) makes a connect() attempt to , which opens a hole in 's NAT but then fails due to a timeout or RST from 's NAT or a RST from itself; (3) closes its connection to and does a listen() on its local port; (4) in turn closes its connection with , signaling to attempt aconnect() directly to .
This sequential procedure may be particularly useful on Windows hosts prior to XP Service Pack 2, which did not correctly implement simultaneous TCP open, or on sockets APIs that do not support the SO_REUSEADDR functionality. The sequential procedure is more timing-dependent, however, and may be slower in the common case and less robust in unusual situations. In step (2), for example, must allow its “doomed-to-fail” connect()attempt enough time to ensure that at least one SYN packet traverses all NATs on its side of the network. Too little delay risks a lost SYN derailing the process, whereas too much delay increases the total time required for hole punching. The sequential hole punching procedure also effectively “consumes” both clients' connections to the server , requiring the clients to open fresh connections to for each new P2P connection to be forged. The parallel hole punching procedure, in contrast, typically completes as soon as both clients make their outgoing connect() attempts, and allows each client to retain and re-use a single connection to indefinitely.
5 Properties of P2P-Friendly NATs
This section describes the key behavioral properties NATs must have in order for the hole punching techniques described above to work properly. Not all current NAT implementations satisfy these properties, but many do, and NATs are gradually becoming more “P2P-friendly” as NAT vendors recognize the demand for peer-to-peer protocols such as voice over IP and on-line gaming.
This section is not meant to be a complete or definitive specification for how NATs “should” behave; we provide it merely for information about the most commonly observed behaviors that enable or break P2P hole punching. The IETF has started a new working group, BEHAVE, to define official “best current practices” for NAT behavior. The BEHAVE group's initial drafts include the considerations outlined in this section and others; NAT vendors should of course follow the IETF working group directly as official behavioral standards are formulated.
5.1 Consistent Endpoint Translation
The hole punching techniques described here only work automatically if the NAT consistently maps a given TCP or UDP source endpoint on the private network to a single corresponding public endpoint controlled by the NAT. A NAT that behaves in this way is referred to as a cone NAT in RFC 3489 [19] and elsewhere, because the NAT “focuses” all sessions originating from a single private endpoint through the same public endpoint on the NAT.
Consider again the scenario in Figure 5, for example. When client initially contacted the well-known server , NAT chose to use port 62000 at its own public IP address, 155.99.25.11, as a temporary public endpoint to representing 's private endpoint 10.0.0.1:4321. When later attempts to establish a peer-to-peer session with by sending a message from the same local private endpoint to 's public endpoint, depends on NAT preserving the identity of this private endpoint, and re-using the existing public endpoint of 155.99.25.11:62000, because that is the public endpoint for to which will be sending its corresponding messages.
A NAT that is only designed to support client/server protocols will not necessarily preserve the identities of private endpoints in this way. Such a NAT is a symmetric NAT in RFC 3489 terminology. For example, after the NAT assigns the public endpoint 155.99.25.11:62000 to client 's session with server , the NAT might assign a different public endpoint, such as 155.99.25.11:62001, to the P2P session that tries to initiate with . In this case, the hole punching process fails to provide connectivity, because the subsequent incoming messages from reach NAT at the wrong port number.
Many symmetric NATs allocate port numbers for successive sessions in a fairly predictable way. Exploiting this fact, variants of hole punching algorithms [9,1] can be made to work “much of the time” even over symmetric NATs by first probing the NAT's behavior using a protocol such as STUN [19], and using the resulting information to “predict” the public port number the NAT will assign to a new session. Such prediction techniques amount to chasing a moving target, however, and many things can go wrong along the way. The predicted port number might already be in use causing the NAT to jump to another port number, for example, or another client behind the same NAT might initiate an unrelated session at the wrong time so as to allocate the predicted port number. While port number prediction can be a useful trick for achieving maximum compatibility with badly-behaved existing NATs, it does not represent a robust long-term solution. Since symmetric NAT provides no greater security than a cone NAT with per-session traffic filtering, symmetric NAT is becoming less common as NAT vendors adapt their algorithms to support P2P protocols.
5.2 Handling Unsolicited TCP Connections
When a NAT receives a SYN packet on its public side for what appears to be an unsolicited incoming connection attempt, it is important that the NAT just silently drop the SYN packet. Some NATs instead actively reject such incoming connections by sending back a TCP RST packet or even an ICMP error report, which interferes with the TCP hole punching process. Such behavior is not necessarily fatal, as long as the applications re-try outgoing connection attempts as specified in step 4 of the process described in Section 4.2, but the resulting transient errors can make hole punching take longer.
A few existing NATs are known to scan “blindly” through packet payloads for 4-byte values that look like IP addresses, and translate them as they would the IP address in the packet header, without knowing anything about the application protocol in use. This bad behavior fortunately appears to be uncommon, and applications can easily protect themselves against it by obfuscating IP addresses they send in messages, for example by sending the bitwise complement of the desired IP address.
5.4 Hairpin Translation
Some multi-level NAT situations require hairpin translation support in order for either TCP or UDP hole punching to work, as described in Section 3.5. The scenario shown in Figure 6, for example, depends on NAT providing hairpin translation. Support for hairpin translation is unfortunately rare in current NATs, but fortunately so are the network scenarios that require it. Multi-level NAT is becoming more common as IPv4 address space depletion continues, however, so support for hairpin translation is important in future NAT implementations.
6 Evaluation of Existing NATs
To evaluate the robustness of the TCP and UDP hole punching techniques described in this paper on a variety of existing NATs, we implemented and distributed a test program called NAT Check [16], and solicited data from Internet users about their NATs.
NAT Check's primary purpose is to test NATs for the two behavioral properties most crucial to reliable UDP and TCP hole punching: namely, consistent identity-preserving endpoint translation (Section 5.1), and silently dropping unsolicited incoming TCP SYNs instead of rejecting them with RSTs or ICMP errors (Section 5.2). In addition, NAT Check separately tests whether the NAT supports hairpin translation (Section 5.4), and whether the NAT filters unsolicited incoming traffic at all. This last property does not affect hole punching, but provides a useful indication the NAT's firewall policy.
NAT Check makes no attempt to test every relevant facet of NAT behavior individually: a wide variety of subtle behavioral differences are known, some of which are difficult to test reliably [12]. Instead, NAT Check merely attempts to answer the question, “how commonly can the proposed hole punching techniques be expected to work on deployed NATs, under typical network conditions?”
NAT Check consists of a client program to be run on a machine behind the NAT to be tested, and three well-known servers at different global IP addresses. The client cooperates with the three servers to check the NAT behavior relevant to both TCP and UDP hole punching. The client program is small and relatively portable, currently running on Windows, Linux, BSD, and Mac OS X. The machines hosting the well-known servers all run FreeBSD.
To test the NAT's behavior for UDP, the client opens a socket and binds it to a local UDP port, then successively sends “ping”-like requests to servers 1 and 2, as shown in Figure 8. These servers each respond to the client's pings with a reply that includes the client's public UDP endpoint: the client's own IP address and UDP port number as observed by the server. If the two servers report the same public endpoint for the client, NAT Check assumes that the NAT properly preserves the identity of the client's private endpoint, satisfying the primary precondition for reliable UDP hole punching.
Figure 8: NAT Check Test Method for UDP
When server 2 receives a UDP request from the client, besides replying directly to the client it also forwards the request to server 3, which in turn replies to the client from its own IP address. If the NAT's firewall properly filters “unsolicited” incoming traffic on a per-session basis, then the client never sees these replies from server 3, even though they are directed at the same public port as the replies from servers 1 and 2.
To test the NAT for hairpin translation support, the client simply opens a second UDP socket at a different local port and uses it to send messages to the public endpoint representing the client's first UDP socket, as reported by server 2. If these messages reach the client's first private endpoint, then the NAT supports hairpin translation.
The TCP test follows a similar pattern as for UDP. The client uses a single local TCP port to initiate outbound sessions to servers 1 and 2, and checks whether the public endpoints reported by servers 1 and 2 are the same, the first precondition for reliable TCP hole punching.
The NAT's response to unsolicited incoming connection attempts also impacts the speed and reliability of TCP hole punching, however, so NAT Check also tests this behavior. When server 2 receives the client's request, instead of immediately replying to the client, it forwards a request to server 3 and waits for server 3 to respond with a “go-ahead” signal. When server 3 receives this forwarded request, it attempts to initiate an inbound connection to the client's public TCP endpoint. Server 3 waits up to five seconds for this connection to succeed or fail, and if the connection attempt is still “in progress” after five seconds, server 3 responds to server 2 with the “go-ahead” signal and continues waiting for up to 20 seconds. Once the client finally receives server 2's reply (which server 2 delayed waiting for server 3's “go-ahead” signal), the client attempts an outbound connection to server 3, effectively causing a simultaneous TCP open with server 3.
What happens during this test depends on the NAT's behavior as follows. If the NAT properly just drops server 3's “unsolicited” incoming SYN packets, then nothing happens on the client's listen socket during the five second period before server 2 replies to the client. When the client finally initiates its own connection to server 3, opening a hole through the NAT, the attempt succeeds immediately. If on the other hand the NAT does notdrop server 3's unsolicited incoming SYNs but allows them through (which is fine for hole punching but not ideal for security), then the client receives an incoming TCP connection on its listen socket before receiving server 2's reply. Finally, if the NAT actively rejects server 3's unsolicited incoming SYNs by sending back TCP RST packets, then server 3 gives up and the client's subsequent attempt to connect to server 3 fails.
To test hairpin translation for TCP, the client simply uses a secondary local TCP port to attempt a connection to the public endpoint corresponding to its primary TCP port, in the same way as for UDP.
The NAT Check data we gathered consists of 380 reported data points covering a variety of NAT router hardware from 68 vendors, as well as the NAT functionality built into different versions of eight popular operating systems. Only 335 of the total data points include results for UDP hairpin translation, and only 286 data points include results for TCP, because we implemented these features in later versions of NAT Check after we had already started gathering results. The data is summarized by NAT vendor in Table 1; the table only individually lists vendors for which at least five data points were available. The variations in the test results for a given vendor can be accounted for by a variety of factors, such as different NAT devices or product lines sold by the same vendor, different software or firmware versions of the same NAT implementation, different configurations, and probably occasional NAT Check testing or reporting errors.
Table 1: User Reports of NAT Support for UDP and TCP Hole Punching
UDP
TCP
Hole
Hole
Punching
Hairpin
Punching
Hairpin
NAT Hardware
Linksys
45/46
(98%)
5/42
(12%)
33/38
(87%)
3/38
(8%)
Netgear
31/37
(84%)
3/35
(9%)
19/30
(63%)
0/30
(0%)
D-Link
16/21
(76%)
11/21
(52%)
9/19
(47%)
2/19
(11%)
Draytek
2/17
(12%)
3/12
(25%)
2/7
(29%)
0/7
(0%)
Belkin
14/14
(100%)
1/14
(7%)
11/11
(100%)
0/11
(0%)
Cisco
12/12
(100%)
3/9
(33%)
6/7
(86%)
2/7
(29%)
SMC
12/12
(100%)
3/10
(30%)
8/9
(89%)
2/9
(22%)
ZyXEL
7/9
(78%)
1/8
(13%)
0/7
(0%)
0/7
(0%)
3Com
7/7
(100%)
1/7
(14%)
5/6
(83%)
0/6
(0%)
OS-based NAT
Windows
31/33
(94%)
11/32
(34%)
16/31
(52%)
28/31
(90%)
Linux
26/32
(81%)
3/25
(12%)
16/24
(67%)
2/24
(8%)
FreeBSD
7/9
(78%)
3/6
(50%)
2/3
(67%)
1/1
(100%)
All Vendors
310/380
(82%)
80/335
(24%)
184/286
(64%)
37/286
(13%)
Out of the 380 reported data points for UDP, in 310 cases (82%) the NAT consistently translated the client's private endpoint, indicating basic compatibility with UDP hole punching. Support for hairpin translation is much less common, however: of the 335 data points that include UDP hairpin translation results, only 80 (24%) show hairpin translation support.
Out of the 286 data points for TCP, 184 (64%) show compatibility with TCP hole punching: the NAT consistently translates the client's private TCP endpoint, and does not send back RST packets in response to unsolicited incoming connection attempts. Hairpin translation support is again much less common: only 37 (13%) of the reports showed hairpin support for TCP.
Since these reports were generated by a “self-selecting” community of volunteers, they do not constitute a random sample and thus do not necessarily represent the true distribution of the NATs in common use. The results are nevertheless encouraging: it appears that the majority of commonly-deployed NATs already support UDP and TCP hole punching at least in single-level NAT scenarios.
There are a few limitations in NAT Check's current testing protocol that may cause misleading results in some cases. First, we only learned recently that a few NAT implementations blindly translate IP addresses they find in unknown application payloads, and the NAT Check protocol currently does not protect itself from this behavior by obfuscating the IP addresses it transmits.
Second, NAT Check's current hairpin translation checking may yield unnecessarily pessimistic results because it does not use the full, two-way hole punching procedure for this test. NAT Check currently assumes that a NAT supporting hairpin translation does not filter “incoming” hairpin connections arriving from the private network in the way it would filter incoming connections arriving at the public side of the NAT, because such filtering is unnecessary for security. We later realized, however, that a NAT might simplistically treat any traffic directed at the NAT's public ports as “untrusted” regardless of its origin. We do not yet know which behavior is more common.
Finally, NAT implementations exist that consistently translate the client's private endpoint as long as only one client behind the NAT is using a particular private port number, but switch to symmetric NAT or even worse behaviors if two or more clients with different IP addresses on the private network try to communicate through the NAT from the same private port number. NAT Check could only detect this behavior by requiring the user to run it on two or more client hosts behind the NAT at the same time. Doing so would make NAT Check much more difficult to use, however, and impossible for users who only have one usable machine behind the NAT. Nevertheless, we plan to implement this testing functionality as an option in a future version of NAT Check.
Despite testing difficulties such as those above, our results are generally corroborated by those of a large ISP, who recently found that of the top three consumer NAT router vendors, representing 86% of the NATs observed on their network, all three vendors currently produce NATs compatible with UDP hole punching [25]. Additional independent results recently obtained using the UDP-oriented STUN protocol [12], and STUNT, a TCP-enabled extension [8,9], also appear consistent with our results. These latter studies provide more information on each NAT by testing a wider variety of behaviors individually, instead of just testing for basic hole punching compatibility as NAT Check does. Since these more extensive tests require multiple cooperating clients behind the NAT and thus are more difficult to run, however, these results are so far available on a more limited variety of NATs.
7 Related Work
UDP hole punching was first explored and publicly documented by Dan Kegel [13], and is by now well-known in peer-to-peer application communities. Important aspects of UDP hole punching have also been indirectly documented in the specifications of several experimental protocols, such as STUN [19], ICE [17], and Teredo [11]. We know of no existing published work that thoroughly analyzes hole punching, however, or that points out the hairpin translation issue for multi-level NAT (Section 3.5).
We also know of no prior work that develops TCP hole punching in the symmetric fashion described here. Even the existence of the crucialSO_REUSEADDR/SO_REUSEPORT options in the Berkeley sockets API appears to be little-known among P2P application developers. NatTrav [4] implements a similar but asymmetric TCP hole punching procedure outlined earlier in Section 4.5. NUTSS [9] and NATBLASTER [1] implement more complex TCP hole punching tricks that can work around some of the bad NAT behaviors mentioned in Section 5, but they require the rendezvous server to spoof source IP addresses, and they also require the client applications to have access to “raw” sockets, usually available only at root or administrator privilege levels.
Protocols such as SOCKS [14], UPnP [26], and MIDCOM [22] allow applications to traverse a NAT through explicit cooperation with the NAT. These protocols are not widely or consistently supported by NAT vendors or applications, however, and do not appear to address the increasingly important multi-level NAT scenarios. Explicit control of a NAT further requires the application to locate the NAT and perhaps authenticate itself, which typically involves explicit user configuration. When hole punching works, in contrast, it works with no user intervention.
Recent proposals such as HIP [15] and FARA [2] extend the Internet's basic architecture by decoupling a host's identity from its location [20]. IPNL [7], UIP [5,6], and DOA [27] propose schemes for routing across NATs in such an architecture. While such extensions are probably needed in the long term, hole punching enables applications to work over the existing network infrastructure immediately with no protocol stack upgrades, and leaves the notion of “host identity” for applications to define.
8 Conclusion
Hole punching is a general-purpose technique for establishing peer-to-peer connections in the presence of NAT. As long as the NATs involved meet certain behavioral requirements, hole punching works consistently and robustly for both TCP and UDP communication, and can be implemented by ordinary applications with no special privileges or specific network topology information. Hole punching fully preserves the transparency that is one of the most important hallmarks and attractions of NAT, and works even with multiple levels of NAT--though certain corner case situations require hairpin translation, a NAT feature not yet widely implemented.
The authors wish to thank Dave Andersen for his crucial support in gathering the results presented in Section 6. We also wish to thank Henrik Nordstrom, Christian Huitema, Justin Uberti, Mema Roussopoulos, and the anonymous USENIX reviewers for valuable feedback on early drafts of this paper. Finally, we wish to thank the many volunteers who took the time to run NAT Check on their systems and submit the results.
Andrew Biggadike, Daniel Ferullo, Geoffrey Wilson, and Adrian Perrig. NATBLASTER: Establishing TCP connections between hosts behind NATs. In ACM SIGCOMM Asia Workshop, Beijing, China, April 2005.
David Clark, Robert Braden, Aaron Falk, and Venkata Pingali. FARA: Reorganizing the addressing architecture. In ACM SIGCOMM FDNA Workshop, August 2003.
Jeffrey L. Eppinger. TCP connections for P2P apps: A software approach to solving the NAT problem. Technical Report CMU-ISRI-05-104, Carnegie Mellon University, January 2005.
Bryan Ford. Scalable Internet routing on topology-independent node identities. Technical Report MIT-LCS-TR-926, MIT Laboratory for Computer Science, October 2003.
Bryan Ford. Unmanaged internet protocol: Taming the edge network management crisis. In Second Workshop on Hot Topics in Networks, Cambridge, MA, November 2003.
Saikat Guha, Yutaka Takeday, and Paul Francis. NUTSS: A SIP-based approach to UDP and TCP network connectivity. In SIGCOMM 2004 Workshops, August 2004.
J. Rosenberg, J. Weinberger, C. Huitema, and R. Mahy. STUN - simple traversal of user datagram protocol (UDP) through network address translators (NATs), March 2003. RFC 3489.
J. Saltzer. On the naming and binding of network destinations. In P. Ravasio et al., editor, Local Computer Networks, pages 311-317. North-Holland, Amsterdam, 1982. RFC 1498.
Michael Walfish, Jeremy Stribling, Maxwell Krohn, Hari Balakrishnan, Robert Morris, and Scott Shenker. Middleboxes no longer considered harmful. In USENIX Symposium on Operating Systems Design and Implementation, San Francisco, CA, December 2004.
"stun" redirects here. For other topics including this term, see stun (disambiguation).
STUN is an Internet standards-track suite of methods, including a network protocol, used in NAT traversal for applications of real-time voice, video, messaging, and other interactive IP communications.
In the original specification in RFC 3489,[1] STUN was an acronym for Simple Traversal of User Datagram Protocol (UDP) through Network Address Translators (NATs), but this title has been changed in a specification of an updated set of methods published as RFC 5389 with the title Session Traversal Utilities for NAT, retaining the same acronym.[2]
The STUN protocol allows applications operating through a network address translator (NAT) to discover the presence of a network address translator and to obtain the mapped (public) IP address (NAT address) and port number that the NAT has allocated for the application's User Datagram Protocol (UDP) connections to remote hosts. The protocol requires assistance from a 3rd-party network server (STUN server) located on the opposing (public) side of the NAT, usually the public Internet. The original version of the protocol also specified methods to ascertain the specific type of NAT, but those methods have been deprecated in the newer specification, because of the plethora of specific NAT implementation behavior in various networking equipment and the resulting intractability of the problem and the deficiencies of the method used.
Network address translation is implemented via a number of different address and port mapping schemes, none of which are standardized.
STUN is not a self-contained NAT traversal solution applicable in all NAT deployment scenarios and does not work correctly with all of them.[2] It is a tool among other methods, most notably Traversal Using Relay NAT (TURN) and Interactive Connectivity Establishment (ICE).
STUN does work with primarily three types: full cone NAT, restricted cone NAT, and port restricted cone NAT. In the cases of restricted cone or port restricted cone NATs, the client must send out a packet to the endpoint before the NAT will allow packets from the endpoint through to the client. STUN does not work with symmetric NAT (also known as bi-directional NAT) which is often found in the networks of large companies. Since the IP address of the STUN server is different than that of the endpoint, in the symmetric NAT case, the NAT mapping will be different for the STUN server than for an endpoint. TURN offers better results with symmetric NAT.
STUN is a light-weight client-server protocol requiring only simple query and response via UDP. The client side is implemented in the user's communications application, such as a Voice over Internet Protocol (VoIP) phone or instant messaging client. The client, operating inside the NAT-masqueraded network, initiates a short sequence of requests to a STUN protocol server listening at two IP addresses in the network on the public side of the NAT, traversing the NAT. The server responds with the results, which are the mapped IP address and port on the 'outside' of the NAT for each request to its two listeners. From the results of several different types of requests, the client application can learn the operating method of the network address translator, including the lifetime of the NAT's port bindings.
STUN usually operates on a User Datagram Protocol (UDP) messaging transport. Since UDP does not provide reliable transport guarantees, reliability is achieved by application-controlled retransmissions of the STUN requests. STUN servers do not implement any reliability mechanism for their responses.[2] When reliability is mandatory, Transmission Control Protocol (TCP) may be used, but induces extra networking overhead. In security-sensitive applications, STUN may be transported and encrypted via TCP/TLS.
An application may automatically determine a suitable STUN server for communications with a particular peer by querying for the stun (for UDP) or stuns (for TCP/TLS) SRVDomain Name System (DNS) resource record, (e.g., _stun._udp.example.com). The standard listening port number for a STUN server is 3478, for UDP and TCP, and 5349 for TLS. Alternately, TLS may also be run on the TCP port if the server implementation can de-multiplex TLS and STUN packets. In case no STUN server is found using SRV lookups, the standard[2] recommends that the destination domain name should be queried for address records (A or AAAA) which would be used with the default port numbers.
In addition to using protocol encryption via TLS, STUN also has built-in authentication and message-integrity mechanisms via specialized STUN packet types.
When a client has discovered its external address, it can communicate with communication peers by advertising its external NAT address to its peers, rather than the masqueraded (internal) address that is not reachable for its peers on the public network. In some cases of NATs (e.g., full-cone type) then either side can initiate communication. With other types (restricted cone or restricted port cone types) both sides must commence transmitting at about the same time to establish the port bindings in the network address translator.
In many application scenarios it is common that both endpoints are located behind a NAT. This double-NAT problem is often not easily overcome even with STUN and sometimes an intermediate application proxy server is required.
The original STUN specification (RFC 3489) used the following algorithm to characterize NAT gateways and firewalls according to the address mapping behavior. This algorithm is not a reliably successful procedure and only applicable to a subset of NAT devices deployed today. The method has therefore been officially removed from the latest version of the standard (RFC 5389).
The algorithm consists of a series of tests to be performed by an application. When the path through the diagram ends in a red box, UDP communication is not possible and when the path ends in a yellow or green box, communication is possible.
The methods of RFC 3489 have proven too unreliable to cope with the plethora of different NAT implementations and application scenarios encountered in production networks. The document is now obsolete. The STUN protocol and method have been updated in RFC 5389, retaining many of the original specifications as a subset of methods, but dropping others.
^RFC 3489, STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs), J. Rosenberg, J. Weinberger, C. Huitema, R. Mahy, The Internet Society (March 2003)
^ abcdRFC 5389, Session Traversal Utilities for NAT (STUN), J. Rosenberg, R. Mahy, P. Matthews, D. Wing, The Internet Society (October 2008)
rndc와 nsupdate는 어떻게 다른가요? 모두 사용해야 만 하나요? ## 이 문서는 "서버관리자를 위한 리눅스 네트워크-(출)베스트북" 책에 대한 독자의 ## 질문 중, 비교적 비중이 있는 질문과 답변을 정리하여 옮겨놓은 것입니다. ## ## 독자의 개인 정보 보호와 스팸메일을 방지하기 위해서 이름과 메일주소는 ## 제외시켰습니다. ## ## 책에 대한 질문은 가능한 ##http://www.linuxchannel.net/board/?table=qna ## 에서 질문해 주십시오. [제목] BIND9 key, rndc.conf, named.conf 설정에 관해서 1. rndc.conf 파일과 named.conf 파일에 설정한 key는 각각 어떤 용도로 사용되나요? 2. rndc.conf 파일과 named.conf 파일에서 server {} 구문의 key 설정이 다른가요? 3. rndc와 nsupdate는 어떻게 다른가요? 모두 사용해야 만 하나요? 4. rndc.conf, named.conf 파일에서 key 부분 설정 구분 정리 1. rndc.conf 파일과 named.conf 파일에 설정한 key는 각각 어떤 용도로 사용되나요? rndc.conf : 이 파일에서 설정한 key는 localhost의 rndc가 사용하고 원격의 네임서버에 인증 요청시 사용하는 key입니다. 즉, localhost의 rndc가 rndc.conf 파일의 server {} 구문 또는 default-server에 설정한 원격의 네임서버(localhost 포함)에 대해서 어떤 제어 메지지를 보낼때 원격의 네임서버로 보내는 인증 key입니다(인증수단에 사용). 제어 메시지는 stop, reload, status, .... 등의 rndc 명령어 로써 start 명령어는 없습니다. 그 대상이 되는 원격 네임서버의 named.conf 파일에서도 똑같은 key가 있어야 합니다(rndc 요청 key와 원격의 네임서버 key가 같아야 함) 참고로, 그 대상이 되는 원격의 네임서버는 rndc.conf 파일의 server {} 구문 으로 설정하거나 rndc의 -s 옵션으로 지정합니다. named.conf : 이 파일에서 설정한 key는 localhost의 named(네임서버)가 사용하며, 이 key로 원격의 다른 네임서버에 인증을 요청하거나, 요청을 받을 때 사용하는 key입니다. 1)인증을 요청할 때 : '인증을 요청할 때'의 경우는 예를 들여, localhost가 2차 네임서버로써 1차 네임서버의 zone 데이터베이스를 백업할 때 이 key로 인증 요청할 경우를 의미합니다(그 외에 어떤 query 전송할 때도 요청에 속함) 설정은 server {} 구문을 사용하여 요청할 원격의 네임서버 주소를 설정합니다. 예) key "key_name" { ...; }; server NS1_ip_addr { // 1차 네임서버 IP 주소, "와 "로 묶지 않음 ...; keys { "key_name"; }; // NS1_ip_addr로 나가는 모든 요청은 key로 인증 // 또는 keys "key_name"; }; 그러나, 반드시 꼭 이 key로 인증하여 zone 데이터베이스를 백업하지는 않습니다. 즉 key가 아닌 호스트, 또는 IP주소로도 얼마든지 인증하여 zone 데이터베이스를 백업할 수 있습니다. 이런 방법을 사용할 경우의 설정은 2차 네임서버의 named.conf 파일에는 key {} 구문이나 server {} 구문은 필요없으며, 1차 네임서버의 options {} 구문이나 각 zone {} 구문에서 'allow-transfer { 2차네임서버_IP주소; };' 으로 설정하면 그만입니다. 2)인증을 요청받을 때 : '인증을 요청받을 때'의 경우는 주로 원격(localhost포함)의 rndc나 원격의 네임서버 또는 원격(localhost)의 nsupdate으로 부터 key를 이용한 인증 요청을 받은 경우를 의미합니다. - 원격(localhost포함)의 rndc 요청 : rndc stop, rndc status, .... - 원격의 네임서버 요청 : zone 데이터베이스를 백업해 갈때, 기타 query - 원격(localhost포함)의 nsupdate 요청 : zone 데이터베이스를 동적으로 갱신할 때 이때의 경우는 server {} 구문은 사용되지 않으며(설정되어 있거나 없거나 상관없음), key {} 구문과 controls {} 구문 설정이 필요합니다. 예) key "key_name" { ...; }; controls { // 인증 요청을 받은 네임서버에서 인증 요청에 대한 어떤 control inet 127.0.0.1 allow { localhost; "요청을 허락할 호스트"; } keys { "key_name"; }; }; // 127.0.0.1의 953번 포트번호 사용 만약 localhost의 rndc나 원격의 rndc 또는 원격의 네임서버 또는 원격의 nsupdate로부터 key를 이용한 아무런 인증을 요청받지 않을 경우에는 key {} 구문과 controls {} 구문은 필요없습니다. 그러나 RPM으로 패키지된 BIND9의 /etc/rc.d/init.d/named 제어 스크립트는 최소한 localhost에서 rndc의 key를 이용한 요청(rndc stop, rndc status, ... 등등)을 받아 named를 종료하기 때문에 key {} 구문 설정과 controls {} 구문이 필요합니다. (만약 자신이 직접 제어스크립트를 만들어 key 없이 named를 종료할 수도 있음) key를 만드는 방법 : # dnssec-keygen -a HMAC-MD5 -b 512 -n HOST key_name 정리 : 이 key의 사용 목적은 localhost의 rndc, named가 원격의 네임서버에 접속하여 어떤 행동(named 제어, zone 데이터베이스의 동적인 갱신, 기타 query)을 취할때 사용되는 인증 방법 중의 하나로써 localhost와 원격의 네임서버에 동일한 key를 가지고 있어야 합니다. 참고로 nsupdate 같은 경우 rndc.conf 또는 named.conf 파일에 설정한 key를 직접적으로 이용하지 않고 dnssec-keygen으로 만든 파일의 key를 이용합니다. 2. rndc.conf 파일과 named.conf 파일에서 server {} 구문의 key 설정이 다른가요? rndc.conf 파일의 server {} 구문은 named.conf 파일의 server {} 구문과 약간 사용법이 다릅니다. rndc.conf 파일의 설정 문법은 named.conf 파일 설정 문법과 비슷하지만 전적으로 같지 않습니다. 예를 들면, rndc.conf 파일에서 include 구문은 사용하면 에러를 낸 경우가 그 일례입니다. rndc.conf 파일 설정 문법은 'man rndc.conf'에서 확인할 수 있습니다. rndc.conf : server remote_NS_ip_addr_or_host { // IP 주소로 설정할 때는 "와 "로 묶어줌 key "key_name"; /*** keys가 아니라 key 임 ***/ }; 이 server {} 구문은 localhost의 rndc가 설정한 원격의 네임서버(localhost포함) 에 "key_name" key로 인증하여 rndc stop, rndc reload등과 같은 명령어를 사용하겠다 는 의미입니다. key를 사용하는 주체는 locahost의 rndc입니다. named.conf : server ip_addr { // host name이 아닌 IP 주소로 "와 "없이 설정해야 함 keys { "key_name"; }; /*** 이 때는 key가 아니라 keys 임 ***/ // keys "key_name"; /*** 이것도 가능 ***/ }; 이 server {} 구문은 localhost의 네임서버가 원격의 ip_addr으로 설정한 네임서버에 대해서 "key_name" key로 인증하겠다는 의미입니다. 즉, 이 설정은 주로 localhost의 2차 네임서버가 원격의 ip_addr으로 설정한 1차 네임서버에 이 key로 인증하여, zone 데이터베이스를 백업할 때에 2차 네임서버에 설정하는 내용입니다. key로 인증하여 zone 데이터베이스를 백업(동기화)하는 방법은 책 p.409 [팁]란에 있습니다. key를 사용하는 주체는 locahost의 네임서버(주로 2차 네임서버)입니다. named.conf 파일에서 사용되는 server {} 구문 사용법은 다음과 같습니다. server ip_addr { [ bogus yes_or_no ; ] [ provide-ixfr yes_or_no ; ] [ request-ixfr yes_or_no ; ] [ edns yes_or_no ; ] [ transfers number ; ] [ transfer-format ( one-answer | many-answers ) ; ]] [ keys { string ; [ string ; [...]] } ; ] }; server {} 구문의 용도 : server {} 구문은 localhost의 rndc 또는 named가 원격의 네임서버에게 어떤 요청을 할때 사용되는 구문입니다. - 원격(localhost포함)의 rndc 요청 : rndc stop, rndc status, .... - 원격의 네임서버 요청 : zone 데이터베이스를 백업해 갈때, 기타 query *주) 책에서는 rndc.conf 파일의 key 설명이 잘못되어 있으므로 아래 URL의 정오를 확인하기 바랍니다. http://linuxchannel.net/books/bookmisp/bookmisp-dns-key.txt 3. rndc와 nsupdate는 어떻게 다른가요? 모두 사용해야 만 하나요? rndc : rndc는 'the Remote Name Daemon Control'로써 원격 네임서버를 제어하는 관리자용 유틸리티 입니다. 즉 원격(localhost포함)의 네임서버를 reload 하거나 refresh, stop, flush, status 등등의 명령어 메시지를 보내 제어하는 툴입니다. [사용법] rndc [-c config] [-s server] [-p port] [-y key] command [command...] [command] reload reload zone refresh zone reconfig stats querylog dumpdb stop halt trace trace level notrace flush status -c 옵션이 없다면 /etc/rndc.conf 파일의 내용이 적용되며, 기본적으로 key를 사용합니다. RPM으로 패키지된 BIND9의 /etc/rc.d/init.d/named 제어 스크립트는 localhost에서 rndc의 key를 이용하여 localhost 자신의 named를 종료하기 때문에 최소한 다음과 같은 설정이 필요합니다. 예) localhost의 rndc.conf 파일 : key rndc_key { algorithm "hmac-md5"; secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; options { default-server localhost; default-key rndc_key; }; 예) localhost named.conf 파일 : key rndc_key { algorithm "hmac-md5"; secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; controls { // 127.0.0.1의 953번 포트 사용 inet 127.0.0.1 allow { localhost; } keys { rndc_key; }; }; 예) 원격의 네임서버 named.conf 파일 : key rndc_key { algorithm "hmac-md5"; secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; controls { // 127.0.0.1의 953번 포트 사용 inet 127.0.0.1 allow { localhost; 허락할_호스트;} keys { rndc_key; }; }; 이와 같은 설정이 되어 있다면, # rndc reload # rndc staus # rndc stop 와 같은 명령을 사용할 수 있습니다. 만약 rndc를 이용하지 않고 named 시작, 종료할 수 있다면(얼마든지 가능함) key 설정은 반드시 필요하지는 않습니다. 이 key는 제어 메시지(명령어)를 보내어 named를 제어할 인증에 관한 한가지 방법입니다. 따라서 반드시 꼭 사용해야만 하는 어떤 규칙은 없지만 RPM으로 패키지된 BIND는 기본적 으로 사용하도록 패키징되어 있을 뿐입니다. nsupdae : nsupdate는 localhost나 원격의 네임서버의 zone 데이터베이스를 동적으로 갱신하고자 할 때 사용하는 관리자용 유틸리티입니다. 1)key 없이 동적으로 원격의 zone 데이터베이스를 갱신할 때 : 원격의 네임서버의 named.conf 파일은 최소한 다음과 같은 설정이 필요합니다. 예) 원격의 named.conf 파일 : zone aaa.co.kr { ...; allow-update { 동적으로_갱신가능한_호스트들; }; }; '동적으로_갱신가능한_호스트들' 부분에는 nsupdate 명령을 보내는 호스트 IP 주소나 호스트 이름을 적어주면 됩니다. 예) nsupdate 사용 예(대화식) : # nsupdate > server 123.123.123.123 /*** 원격의 네임서버 IP 또는 호스트 이름 ***/ > zone aaa.co.kr. /*** 업데이트할 zone 지정 ***/ > prereq nxdomain w3.aaa.co.kr. /*** 현재 호스트(w3)가 없음을 조건으로 알림 ***/ > update add w3.aaa.co.kr. 86400 CNAME www.aaa.co.kr. /*** w3 호스트 추가 ***/ > show /*** 현재까지 사용한 명령어 보기 ***/ > send /*** 명령어를 123.123.123.123에게 전송함 ***/ > quit /*** 종료함 ***/ 기타 자세한 명령어는 책 p.458에 설명되어 있으므로 참고하도록 하세요. (또는 man nsupdate) 예) nsupdate 사용 예(비대화식) : # cat nsupdate-aaa.co.kr.cmd /*** 파일을 직접 작성함 ***/ server 123.123.123.123 zone aaa.co.kr. prereq nxdomain w3.aaa.co.kr. update add w3.aaa.co.kr. 86400 CNAME www.aaa.co.kr. show send quit # # nsupdate nsupdate-aaa.co.kr.com 2)key를 사용하여 동적으로 원격의 zone 데이터베이스를 갱신할 때 : 우선 localhost의 nsupdate가 사용할 key를 만들고 이 key를 원격의 named.conf 파일에 설정해야 합니다. 예제에서는 key 이름을 'mykey'로 가정함. # dnssec-keygen -a HMAC-MD5 -b 512 -n HOST mykey # # ls Kmykey.+157+46093.key /*** 매번 파일 이름이 다름 ***/ Kmykey.+157+46093.private xxx.private을 열어서 key 부분을 원격의 네임서버에 다음과 같이 설정합니다. 예) 원격의 named.conf 파일 : key mykey { algorithm "hmac-md5"; secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; controls { // 127.0.0.1의 953번 포트 사용 inet 127.0.0.1 allow { localhost; 허락할_호스트;} keys { mykey; }; }; zone aaa.co.kr { ...; allow-update { key "mykey"; }; /*** keys가 아니라 key ***/ }; 예) nsupdate 사용 예 : # ls /*** 다음 두개의 파일 모두 있어야 함 ***/ Kmykey.+157+46093.key Kmykey.+157+46093.private # # nsupdate -k Kmykey.+157+46093.private > nsupdate 나머지 nsupdate 명령어는 1)번과 동일하므로 생략합니다. 제대로 업데이트되었는지 확인하는 방법은 nslookup, dig, host로 직접 확인해 보세요. 원격의 네임서버에서는 임시로 zone-file.jnl 파일을 만들며 몇 분이 지나면 자동적으로 zone-file(데이터베이스 파일)이 갱신하기 때문에 다른 조치를 취할 필요는 없습니다. *주의할 점) 원격의 네임서버의 zone 데이터베이스 디렉토리와 해당 zone 데이터베이스 파일은 named의 유저(예:named, ps -ef | grep named로 확인)에게 쓰기 권한(퍼미션)이 있어야 합니다. 그래야 업데이트되기 때문에... *참고로) 2차 네임서버는 1차 네임서버에 실시간으로 접속하여 zone 데이터베이스를 백업하여 자신(2차 네임서버)의 zone 데이터베이스를 갱신해야하기 때문에 allow-update { none; } 와 같은 구문을 설정하면 안됩니다. 정리 : - rndc : localhost나 원격의 네임서버에 stop, reload, staus 등의 제어 메시지를 보낼때 - nsupdate : localhost나 원격의 네임서버의 zone 데이터베이스를 동적으로 갱신하고자 할 때 따라서 네임서버를 운영할 때 반드시 이 두개의 유틸리티는 필요하지는 않지만 rndc를 이용하여 localhost의 named를 제어할 뿐입니다. 4. rndc.conf, named.conf 파일에서 key 부분 설정 구분 정리 address_match_list = address_match_list_element ; [ address_match_list_element; ... ] address_match_list_element = [ ! ] (ip_address [/length] | key key_id | acl_name | { address_match_list } ) *주) 다음 표에서 address_match_list로 설정가능한 구문에서 key로 설정할 경우, keys "key_name"이 아니라 key "key_name"입니다. named.conf rndc.conf key "key_name" { ...; }; or include "/etc/rndc.conf"; 보통 include "/etc/rndc.conf";로 설정되어 있음. key "key_name" {} 구문은 named.conf와 동일하지만 include 구문을 사용할 수 없기 때문에 직접 구문을 설정해야 함. server ip_addr { ...; keys { "key_name"; }; // keys "key_name"; // 이것도 가능 }; *주) ip_addr 부분에 host_name이나 "와 "로 묶어서 설정하면 구문에러가 나므로 "없이 ip 주소로만 설정해야 함 server ip_addr_or_host_name { key "key_name"; }; *주) ip_addr_or_host_name 부분에 ip_addr로 설정할 경우 "와 "로 묶어줘야 구문에러가 없음 acl acl-name { address_match_list }; - controls { inet ( ip_addr | * ) [ port ip_port ] allow { address_match_list } keys { key_list }; [ inet ...; ] }; *주) key_list에 "key_name"하나 또는 ';'로 구분하여 여러개 설정함. - allow-notify { address_match_list }; allow-query { address_match_list }; allow-transfer { address_match_list }; allow-recursion { address_match_list }; allow-v6-synthesis { address_match_list }; blackhole { address_match_list }; listen-on { address_match_list }; listen-on-v6 { address_match_list }; *주) options {} 구문의 sub 구문에 모두 속함. - allow-notify { address_match_list }; allow-query { address_match_list }; allow-transfer { address_match_list }; allow-update { address_match_list }; update-policy { update_policy_rule [...] }; allow-update-forwarding { address_match_list }; masters { ip_addr [key "key_name"]; [...] }; *주) zone {} 구문의 sub 구문에 모두 속함. - match-clients { address_match_list }; match-destinations { address_match_list }; *주) view {} 구문의 sub 구문에 모두 속함. - -- Jaehun, Park (jaehun@new21.com) New21 Community Server & Secure Team
이 문서는 LVM이란 무엇이고, 어떻게 작동하고, 여러분의 생활을 쉽게 할수 있도록 LVM을 사용할수 있는 방법에 관해 여러분에게 알려주는데 도움을 주기 위해 쓰여졌다. 현재 LVM FAQ와 German HOWTO도 있지만, 이 문서는 기존 문서와는 다른 면에서 쓰여 졌다. 이 문서는 매우 간단한 'HOWTO' 인 반면, 또한 이해도 줄 수 있다.(그러길 바란다.)
나는 Linux Logical Volume Manager 저자가 아님을 명백히 밝힌다. 나는 개발한 사람들을 많이 존경하며, 그들과 상호 협력하길 바란다.
매우 이상하겠만, 나는 LVM의 개발자들을 알지 못한다. 나는 이러한 상황이 곧 바뀌길 바란다. 개발자들의 기분이나 입장을 고려하지 못한 점에 대해서 미리 사과한다.
This document is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
If your disks melt and your company fires you - it's never our fault. Sorry. Make frequent backups and do your experiments on non-mission critical systems.
Furthermore, Richard Allen does not speak for his employer.
Linux is a registered trademark of Linus Torvalds.
그렇게 많이 필요하지 않다. 만일 여러분이 Linux를 설치한 경험이 있고 filesystem(fdisk/mkfs)을 만들었다면, 여러분은 모두 설정해야 된다. 루트로써 작업할때는 항상 신중 해라. 잘못된 명령어나 장치 파일들에 대한 어떠한 작업들은 존재하는 데이타를 손상시킬수 있다.
만일 여러분이 HP/UX LVM을 설정하는 방법을 안다면, 여러분은 이미 거의 한거나 마찬가지다. 리눅스는 HP 실행과 거의 같다.
이 문서에 관해 주의해야 할 몇 가지가 있다. 내가 이 문서의 대부분을 썼지만, 나는 실제로 이러한 방법으로 이 문서를 유지하길 원하지 않는다. 나는 Open Source에 대한 지지자이며, 여러분들의 feedback, 갱신, 패치등을 원한다. 오타나 에러들에 관해 나에게 알리는걸 주저하지 마라.
만일 여러분이 섹션을 유지하는데 더 좋은 자격이 있거나 새로운 섹션의 저자이고 유지할수 있다면, 그렇게 하길 환영한다. 이 HOWTO의 SGML문서는 CVS로 이용할 수 있다. 나는 이 작업이 상호 협동적인 프로젝트가 되길 바란다.
이러한 목적으로, 여러분은 FIXME의 많은 주의 사항들을 발견할 것이다. 패치들은 항상 환영한다. 여러분이 FIXME를 발견하는 곳이 어디든, 여러분은 여러분이 잘 알지 못하는 분야를 다루고 있다는 것을 알아야 한다. 이것은 그밖의 곳에 에러가 없다는것을 말하는 것은 아니다. 단지 주의하라는 것이다. 만일 여러분이 유효한 것을 가지고 있다면, 우리가 알수 있도록 해라. 그러면 나는 FIXME의 주의사항에서 제거할 것이다.
전통적으로, 파티션 크기는 고정적이다. 이것은 시스템 설치자는 "나는 이 파티션에 얼마나 많은 데이타를 저장할 것이다"가 아니라 "나는 이 파티션에 얼마 이상을 저장할 것이다"라는 질문을 고려할 것을 요구한다. 사용자가 파티션 공간을 모두 사용하였을때, 보통은 파티션을 다시 잡든지 (전체 운영 시스템의 reload를 의미한다.) 심볼릭 링크 같은 방법으로 해결을 한다.
파티션은 물리 디스크의 연속된 블럭들이다라는 생각은 계속 바뀌었다. 대부분의 유닉스 시스템들은 물리 디스크를 몇몇 단위(unit)들로 나눌수 있는 능력을 가지고 있다. 다중 드라이브에서 저장 단위들은 "논리적인 volume"으로 모아지고, 이것들이 파티션으로 할당된다. 추가적으로, 단위(unit)들은 원하는 공간처럼 파티션에서 추가되거나 제거될 수 있다.
이것이 논리적인 볼륨 관리자(LVM)의 기본적인 생각이다.
예를 들어, 여러분이 1G 디스크를 가지고 있고, 600MB를 사용할수 있는 "/home" 파티션을 만든다고 하자. 그리고 여러분이 할당한 공간을 모두 사용하였는데 "/home"에서 1G를 사용할 필요가 있다고 가정하자. 파티션의 예전 개념을 사용하면, 여러분은 1GB의 다른 드라이브를 가지길 원할 것이다. 그리고 여러분은 디스크를 추가하고, 새로운 "/home"을 만들고 현재 존재하는 데이타를 복사할 것이다.
그러나, LVM 설정으로, 여러분은 단순히 400MB(또는 더) 디스크를 추가할 수 있고, 저장 단위(unit)들을 "/home" 파티션에 추가할 수 있다. 다른 툴들은 지금의 파일 시스템을 재 조정할수 있도록 허용하며, 여러분이 더 커다란 파티션 크기로 재 조정할 수 있고 원래의 비지니스로 돌아갈수 있다.
매우 특별한 경우로써, LVM은 이동할수 없는 타켓의 백업을 만들수 있도록 자체적인 "snapshots"을 만들수도 있다. 우리는 이러한 흥미로운 가능성으로 돌아가서, 이것은 다른 많은 실제 어플리케이션을 가진다.
다음 섹션에서 우리는 LVM의 기초를 설명하고 LVM이 사용하는 여러 추상적 개념에 대해서도 설명한다.
여러분에게 겁을 주기 위해서가 아니라, LVM은 여러분의 파일 시스템을 위험하게 하지 않도록 하기 위한 용어에서 왔다.
다소, 밑바닥 부터 시작하자.
물리적 미디어
우리가 단순히 하드 디스크나 파티션을 가정하였다 할지라도, 여러분은 어림 잡아서 '물리적' 이라는 말을 이해해야 한다. 예를 들어, /dev/hda, /dev/hda6, /dev/sda. 여러분은 블럭 장치의 연속적인 블럭 수들을 바꿀수 있다.
물리적 볼륨(Volume) (PV)
PV는 단지 여기에 추가된 관리 데이타를 가지는 물리적 미디어이다. -- 일단 여기에 추가하면, LVM은 이것을 소유한 것처럼 인식한다.
물리적 확장(PE)
물리적 확장(Physical Extents)은 메가 바이트 크기를 가지는 큰 블럭같은 것이다. PEs는 할당될 수 있다.
볼륨 그룹(Volume Group)
VG는 물리적 확장의 수(여러 물리적 볼륨이나 하드 드라이브가 기본인)로 이루어 진다. 이것을 여러 하드 드라이브(예를 들어, /dev/hda 와 /dev/sda)로 이루어져 있는 것 같은 VG로 생각할수 있지만, 이것은 이들 하드 드라이브가 제공하는 PE들을 포함한다고 말하는 것이 더 정확하다.
>From this Volume Group, PEs can be assigned to a ...
논리적 볼륨(LV)
우리는 마지막으로 갖는 것이 있다. 논리적 볼륨은 모든 작업의 결과이며 우리는 정보를 여기에 저장한다. 이것은 파티션에 대한 생각과 동일한 것이다.
정규 파티션처럼, 논리적 볼륨은 전형적으로 만들어 진다.
파일 시스템
이 파일 시스템은 여러분이 원하는 모든 것이다.: 표준 ext2, ReiserFS, NWFS, XFS, JFX, NTFS 등등. 리눅스 커널에서, 정규 파티션과 논리적 볼륨사이에는 아무런 차이가 없다.
나는 여러분이 쉽게 이것을 볼수 있도록 하기 위해 ASCII 챠트로 만들었다.
물리적 확장을 포함한, 물리적 볼륨:
+-----[ Physical Volume ]------+
| PE | PE | PE | PE | PE | PE |
+------------------------------+
6개의 물리적 확장과 2개의 물리적 볼륨(PVs)를 포함한 볼륨 그룹:
+------[ Volume Group ]-----------------+
| +--[PV]--------+ +--[PV]---------+ |
| | PE | PE | PE | | PE | PE | PE | |
| +--------------+ +---------------+ |
+---------------------------------------+
우리는 여기에 더 추가 확장을 하였다.:
+------[ Volume Group ]-----------------+
| +--[PV]--------+ +--[PV]---------+ |
| | PE | PE | PE | | PE | PE | PE | |
| +--+---+---+---+ +-+----+----+---+ |
| | | | +-----/ | | |
| | | | | | | |
| +-+---+---+-+ +----+----+--+ |
| | Logical | | Logical | |
| | Volume | | Volume | |
| | | | | |
| | /home | | /var | |
| +-----------+ +------------+ |
+---------------------------------------+
이것은 두 디스크에 걸친 두 파일 시스템을 우리에게 보여준다. /home 파일 시스템은 4개의 물리적 확장을, /var 파일 시스템은 2개의 물리적 확장을 포함한다.
bert hubert는 더욱 시각적으로 LVM을 보여주기 위해 툴 을 만들었다. screenshot도 있다. ASCII 차트보다 더 좋게 보인다.
이 부분은 이해하기 어렵다. 그래서 논리적 볼륨을 만드는 예제에 주석을 달았다. 이 예제를 콘솔에 복사하지 마라. 왜냐하면 만일 여러분의 컴퓨터가 /dev/hda3와 /dev/hdb2를 사용하지 않는다면, 여러분의 데이타를 파괴하기 때문이다.
의문스럽다면, 위의 ASCIIgram을 봐라.
여러분은 /dev/hda3와 /dev/hdb2 파티션 타입을 0x8e, 즉 'Linux LVM'으로 설정해야 한다. fdisk의 버전이 이 타입을 아직 알지 못해 'Unknown'으로 나오는지 확인해라.:
# fdisk /dev/hda
Command (m for help): p
Disk /dev/hda: 255 heads, 63 sectors, 623 cylinders
Units = cylinders of 16065 * 512 bytes
Device Boot Start End Blocks Id System
/dev/hda1 1 2 16033+ 83 Linux
/dev/hda2 3 600 4803435 83 Linux
/dev/hda3 601 607 56227+ 83 Linux
/dev/hda4 608 614 56227+ 83 Linux
Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 8e
Command (m for help): p
Disk /dev/hda: 255 heads, 63 sectors, 623 cylinders
Units = cylinders of 16065 * 512 bytes
Device Boot Start End Blocks Id System
/dev/hda1 1 2 16033+ 83 Linux
/dev/hda2 3 600 4803435 83 Linux
/dev/hda3 601 607 56227+ 8e Unknown
/dev/hda4 608 614 56227+ 83 Linux
Command (m for help): w
우리는 /dev/hdb2도 했지만, 여기서는 보여주지 않았다. 이것은 LVM이 여러분의 설정을 잃은 것들을 재구성하기 위해 필요하다.
지금, 이것이 필요하지는 않지만, 몇몇 컴퓨터는 여기서 재부팅을 요구하기도 한다. 그래서 만일 다음 예제가 제대로 작동하지 않는다면, 재 부팅해라.
그리고, 우리는 다음처럼 물리적 볼륨을 만든다.:
# pvcreate /dev/hda3
pvcreate -- physical volume "/dev/hda3" successfully created
# pvcreate /dev/hdb2
pvcreate -- physical volume "/dev/hdb2" successfully created
그리고, 우리는 이들 두개의 PVs를 'test'라 불리는 볼륨 그룹에 추가한다:
# vgcreate test /dev/hdb2 /dev/hda3
vgcreate -- INFO: using default physical extent size 4 MB
vgcreate -- INFO: maximum logical volume size is 255.99 Gigabyte
vgcreate -- doing automatic backup of volume group "test"
vgcreate -- volume group "test" successfully created and activated
그래서, 우리는 빈 볼륨 그룹을 가지게 되며, 이제 비트(bit)를 검사하도록 하자.
# vgdisplay -v test
--- Volume group ---
VG Name test
VG Access read/write
VG Status available/resizable
VG # 0
MAX LV 256
Cur LV 0
Open LV 0
MAX LV Size 255.99 GB
Max PV 256
Cur PV 2
Act PV 2
VG Size 184 MB
PE Size 4 MB
Total PE 46
Alloc PE / Size 0 / 0
Free PE / Size 46 / 184 MB
--- No logical volumes defined in test ---
--- Physical volumes ---
PV Name (#) /dev/hda3 (2)
PV Status available / allocatable
Total PE / Free PE 13 / 13
PV Name (#) /dev/hdb2 (1)
PV Status available / allocatable
Total PE / Free PE 33 / 33
여기에 있는 많은 데이타들 - 이 데이타중 대부분은 지금 이해해야 한다. 우리는 여기에 정의된 어떠한 논리적 볼륨도 없어서 이걸 치료해야 한다. 우리는 볼륨 그룹 'test'에 'HOWTO'라 불리는 50 메가 바이트 볼륨을 만들도록 한다.:
# lvcreate -L 50M -n HOWTO test
lvcreate -- rounding up size to physical extent boundary "52 MB"
lvcreate -- doing automatic backup of "test"
lvcreate -- logical volume "/dev/test/HOWTO" successfully created
자, 여기서 파일 시스템을 만들도록 하자.
# mke2fs /dev/test/HOWTO
mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
13328 inodes, 53248 blocks
2662 blocks (5.00%) reserved for the super user
First data block=1
7 block groups
8192 blocks per group, 8192 fragments per group
1904 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
# mount /dev/test/HOWTO /mnt
# ls /mnt
lost+found
다 했다. 이제 볼륨 그룹을 다시 보도록 해라. 왜냐하면, 지금쯤 비트(bit)가 채워져야 하기 때문이다.
# vgdisplay test -v
--- Volume group ---
VG Name test
VG Access read/write
VG Status available/resizable
VG # 0
MAX LV 256
Cur LV 1
Open LV 1
MAX LV Size 255.99 GB
Max PV 256
Cur PV 2
Act PV 2
VG Size 184 MB
PE Size 4 MB
Total PE 46
Alloc PE / Size 13 / 52 MB
Free PE / Size 33 / 132 MB
--- Logical volume ---
LV Name /dev/test/HOWTO
VG Name test
LV Write Access read/write
LV Status available
LV # 1
# open 1
LV Size 52 MB
Current LE 13
Allocated LE 13
Allocation next free
Read ahead sectors 120
Block device 58:0
--- Physical volumes ---
PV Name (#) /dev/hda3 (2)
PV Status available / allocatable
Total PE / Free PE 13 / 13
PV Name (#) /dev/hdb2 (1)
PV Status available / allocatable
Total PE / Free PE 33 / 20
자, 됐다. /dev/hda3는 완전히 사용되지는 않았지만, /dev/hdb2는 13개의 물리적 확장을 사용하고 있다.
모든 운영체제처럼, Linux도 두 부분으로 나누어져 있다.:커널 영역과 유저 영역. 유저 영역은 가끔 userland라 불리며, 이것은 'Userland'를 위한 좋은 이름이기도 하다.
논리적 볼륨 관리를 포함하는 복구, 생성과 수정과 같은 것들은 유저 영역에서 행해 지며, 그리고 커널과 통신한다. 일단 볼륨 그룹과 논리적인 볼륨이 커널에 보고되면, '활성화'라 불린다. 어떤 변화들은 엔터티(entity)가 활성화될때만 이루어지며, 어떤 것들은 비 활성화되었을때 이루어진다.
오프 라인이라는 것은, 여러분이 파일 시스템을 늘리는 작업을 하기 위해 파일 시스템을 언마운트하는 것을 의미한다. 파일 시스템과 데이타는 이 작업동안은 이용할수 없다. 만일 루트 크기나 다른 중요한 파티션의 크기를 확장한다면, 여러분은 다른 부트 미디어를 사용해야 한다.
ext2resize 툴은 GNU ftp 사이트에서 이용할수 있지만, 대부분의 배포판은 패키지로서 제공한다. 문법은 매우 명확하다.:
이것은 LVM 의 장점중의 하나이다. 한번 디스크에서 에러가 발견되기 시작하면, 자료를 이동시켜야 할 적절한 시기이다. LVM 을 이용하면 이것은 매우 쉽다. 먼저 확실한 교체 예제를 들도록 보도록 하는데, 이것은 당신이 적어도 당신이 교체하고 하는 것만큼의 용량을 가진 디스크를 시스템에 추가하는 것이다.
자료를 이동하기 위해서는, Volume Group 의 Physical Extents 를 다른 디스크로 이동하는데, 보다 정확하게 말하면, 다른 Physical Volume 으로 이동하는 것이다. 이것을 위해서 LVM 은 pvmove 유틸리티를 제공한다.
우리의 의심스런 디스크는 /dev/hda1 이고 그것을 /dev/sdb3 로 교체하려고 한다고 가정하자. 먼저 /dev/sdb3 를 /dev/hda1 을 포함하는 Volume Group 에 추가한다.
이것을 하기 전에 이 볼륨 그룹에 있는 어떠한 파일시스템이라도 언마운트 하는 것이 좋을 것 같다. 풀 백업 또한 손해보지는 않을 것이다.
FIXME: 이것이 필요할까?
그리고 나서 pvmove을 실행한다. 가장 간단한 사용법에서는 단지 제거하고자 하는 디스크만을 언급한다. 다음과 같다:
# pvmove /dev/hda1
pvmove -- moving physical extents in active volume group "test1"
pvmove -- WARNING: moving of active logical volumes may cause data loss!
pvmove -- do you want to continue? [y/n] y
pvmove -- doing automatic backup of volume group "test1"
pvmove -- 12 extents of physical volume "/dev/hda1" successfully moved
이 경고를 주의하기 바란다. 또한, 적어도 어떤 커널이나 LVM 버전은 이 명령과 문제가 있는 것으로 보인다. 필자는 2.3.99pre6-2 로 테스트했고, 동작은 했지만, 경고를 받았다.
이제 더이상 /dev/hda1 이 Physical Extents 를 갖고 있는 않으므로, 그것을 볼륨 그룹에서 제거할 수 있다.
# vgreduce test1 /dev/hda1
vgreduce -- doing automatic backup of volume group "test1"
vgreduce -- volume group "test1" successfully reduced by physical volume:
vgreduce -- /dev/hda1
FIXME: 몇가지에 대해 명확히 할 필요가 있다. 볼륨 그룹이 활성화되어야 하는가? 언제 데이터를 잃게 될까?
만약 디스크가 경고 없이 고장났고 물리적 확장(PE) 를 다른 물리적 볼륨(PV) 로 옮길 수 없다면, 문제가 생긴 PV 에 있는 논리적 볼륨(LV)이 미러되고 있지 않는 한은 자료를 잃게 될 것이다. 취해야 할 조치의 정확한 방법은 문제가 생긴 PV 를 동일하거나 적어도 같은 크기의 파티션으로 교체하는 것이다.
/etc/lvmconf 디렉토리에는 디스크들을 물리적 볼륨(PV) 으로 만드는 LVM 자료와 스트럭쳐들과 물리적 볼륨이 어느 볼륨 그룹에 속해 있는지, 볼륨 그룹에는 어떤 논리적 볼륨이 있는지에 대한 백업을 담고 있다.
고장난 디스크를 교체하고 난 후에는 vgcfgrestore 명령어를 사용하여 LVM 자료를 새로운 PV 에 복구할 수 있다. 이것은 볼륨 그룹과 그것의 모든 정보를 복구하지만, 논리적 볼륨에 있던 자료들은 복구하지 않는다. 이것이 대부분의 LVM 명령들이 변화가 생길때 자동으로 LVM 자료를 백업하는 이유이다.
이것은 보다 믿을수 없는 기능중의 하나이다. 당신에게는 많은 작업을 하고 있는 바쁜 서버가 있다고 하자. 유용한 백업을 위해서는, 많은 프로그램들을 셧다운 해야 하는데, 그렇지 않으면 자료가 백업당시와 변동된 상태로 끝나기 때문이다.
표준적인 예제는 파일을 /tmp 에서 /root 로 옮기는 것인데, /root 는 첫번째로 백업되는 곳이다. /root 가 읽혀졌을때, 파일은 아직 거기에 있지 않다. /tmp 가 백업될때는, 그 파일은 그곳에 없다.
또다른 예로는 데이터베이스나 디렉토리를 저장하는 것이 있다. 우리가 완전한 셧다운을 할 시간을 어플리케이션에 주지 않는 한은, 파일이 사용가능한 상태에 있는지 확인할 수 있는 단서가 없다.
또다른 문제가 생길 수도 있다. 우리는 어플리케이션을 셧다운하고, 백업을 하고, 어플리케이션을 다시 시작한다. 이것은 백업이 단 몇분만에 된다면 괜찮지만, 만약 여러 시간이 걸리거나 얼마나 오래 걸릴지 확신할수 조차 없다면 정말로 골치가 아프다.
LVM 은 이에 대한 해결책이다.
LVM 을 이용하여 논리적 볼륨에 대한 즉각적인 스냅샷 사진을 찍고, 그것을 마운트해서 그에 대한 백업을 만들 수 있다.
이렇게 해보자:
# mount /dev/test/HOWTO /mnt
# echo > /mnt/a.test.file
# ls /mnt/
a.test.file lost+found
# ls -l /mnt/
total 13
-rw-r--r-- 1 root root 1 Apr 2 00:28 a.test.file
drwxr-xr-x 2 root root 12288 Apr 2 00:28 lost+found
좋아, 이제 작업할 것이 생겼다. 스냅샷을 만들어보자:
# lvcreate --size 16m --snapshot --name snap /dev/test/HOWTO
lvcreate -- WARNING: all snapshots will be disabled if more than 16 MB are changed
lvcreate -- INFO: using default snapshot chunk size of 64 KB
lvcreate -- doing automatic backup of "test"
lvcreate -- logical volume "/dev/test/HOWTO" successfully created
'--size' 파라미터는 나중에 더 자세히 다루겠다. 스냅샷을 마운트하자:
# mount /dev/test/snap /snap
# ls /snap
total 13
-rw-r--r-- 1 root root 1 Apr 2 00:28 a.test.file
drwxr-xr-x 2 root root 12288 Apr 2 00:28 lost+found
이제 원본으로부터 a.test.file 을 지우고, 스냅샷에 여전히 그것이 있는지 확인해보자:
우리가 '--size' 파라미터를 설정해야 했음을 기억하는가? 실제로 일어나는 것은 'snap' 볼륨이 모든 블럭들의 사본, 혹은 LVM 이 그것들을 부르는 이름인 'chunks' 를 가지기를 필요로 하는 것인데, 이것은 원본에서 변경된 것이다.
우리가 a.test.file 을 삭제했을때, 그것의 inode 가 삭제되었다. 이것은 64KB를 'dirty' 상태로 표기하게 만들고 - 원본 자료의 사본은 'snap' 볼륨에 쓰여졌다. 이 경우에 우리는 스냅샷에 16MB 를 할당했고, 그래서 만약 16MB 이상의 'chunks' 가 수정되었다면, 스냅샷은 비활성화 될 것이다.
스냅샷 파티션에 대한 정확한 크기를 결정하기 위해서는, 프라이머리 LV 의 사용 경향과 스냅샷에 활성화될 시간의 길이에 기반해서 추측해야 한다. 예를 들어, 아무도 시스템을 사용하지 않는 한밤중에 하는 한시간짜리 백업은 공간을 거의 필요로 하지 않을 것이다.
스냅샷이 persistent 하지 않다는 점에 유의하라. 만약 LVM 을 unload 하거나 리부트한다면, 그것들은 사라지고, 다시 만들어져야 한다.
성능상의 이유로, 여러개의 디스크에 'stripe' 로 자료를 분산해두는 것이 가능 하다. 이것은 블럭 1이 물리적 볼륨 A 에, 블럭 2가 물리적 볼륨 B 에 있고, 다시 블럭 3이 물리적 볼륨 A 에 있음을 의미한다. 또한 2개 이상의 디스크에 스트라이 프 할 수도 있다.
이러한 배열은 더 많은 디스크 대역폭을 이용가능함을 의미한다. 또한 보다 많은 'spindles' 가 포함된다. 뒤에서 더 자세히 다루겠다.
성능을 향상시킬 뿐 아니라, 자료의 사본을 여러개의 디스크에 보관하는 것도 가능 하다. 이것은 미러링(mirroring) 이라고 불린다. 현재, LVM 자체에서는 이것을 지원하지 않지만, 미러링을 할 수 있는 방법은 있다.
디스크 성능은 적어도 세가지 요소에 의해 영향을 받는다. 가장 명백한 것은 디스크에서 자료가 순차적으로 읽혀지거나 쓰여지는 속도이다. 이것은 SCSI/IDE 버스에서 그것에 물려있는 단일 디스크에서 파일을 읽거나 쓸때 제한 요소이다.
그 후에는 디스크로 이용가능한 대역폭이 있다. 한개의 SCSI 버스에 7개의 디스크 가 있다면, 이것은 디스크 자체의 쓰기 속도보다 작을수도 있다. 만약 충분한 메모리를 사용한다면, 이러한 병목점이 문제가 되는것을 막을수도 있다.
그리고 레이턴시도 있다. as the saying goes, 레이턴시는 언제나 나쁜 소식이다. 그리고 더 안좋은 것은, 레이턴시를 낮추기 위해서는 더 많은 돈을 쓸 수도 없다 는 것이다. 오늘날 대부분의 디스크들은 7ms 정도의 레이턴시를 갖는 것으로 보인 다. 그 뒤에는 SCSI 레이턴시도 있는데, 25ms 정도가 된다.
FIXME: 최근의 수치들이 필요하다!
이것은 무엇을 의미할까? 합쳐진 레이턴시가 전형적인 경우엔 30ms 근방이 될 것이라는 것이다. 그래서 초당 33 번 정도의 디스크 작업만을 수행할 수 밖에 없다. 만약 초당 수천번 이상의 쿼리를 할 수 있기를 원하지만, 거대한 캐쉬를 갖고 있지 못할 경우라면, 당신은 매우 운이 없는 것이다.
만약 병렬로 동작하는 여러개의 디스크나, 'spindles' 를 갖고 있다면, 동시에 여러개의 명령어를 실행시킬 수 있는데, 이것은 훌륭하게 레이턴시 문제를 피해가는 방법이다. 어떤 어플리케이션들은, 거대한 뉴스 서버와 같은 것들은, 스트라이핑이나 다른 IO 현명함(smartness) 없이는 더이상 동작할 수 없다.
이것이 스트라이핑이 하는 것이다. 만약 당신의 버스가 그것에 도달한다면 (if your bus is up to it), 순차적인 읽기와 쓰기조차도 빨라질 수 있다.
추가의 방법이 수반되지 않는 스트라이핑은 실패 확률을, '비트 당'으로 증가 시킨다. 만약 당신의 디스크중 어떤 것이라도 고장난다면, 전체의 논리적 볼륨이 사라져버린다. 만약 단순히 데이터를 연결하기(concatenate)만 한다면, 파일 시스템의 일부분만을 잃게 될 것이다.
스트라이프 설정을 지정하는 것은 lvcreate 로 논리적 볼륨을 생성할때 완료된다. 그중에는 두가지 관련있는 파라미터가 있다. -i 를 이용해 LVM 이 얼마나 많은 물리적 볼륨을 분산시켜 사용해야 하는지를 지시할 수 있다. 스트라이핑은 실제로 bit-by-bit 기반으로 행해지지는 않으며, 블럭상에서 일어난다. -I 로는 킬로바이트 단위로 설정할 수 있다. 이것은 2의 거듭제곱 형태가 되어야 함과, 가장 조잡한 뭉치회는 128Kbyte 임을 유의하라.
예제:
# lvcreate -n stripedlv -i 2 -I 64 mygroup -L 20M
lvcreate -- rounding 20480 KB to stripe boundary size 24576 KB / 6 PE
lvcreate -- doing automatic backup of "mygroup"
lvcreate -- logical volume "/dev/mygroup/stripedlv" successfully created
만약 같은 디스크에서 2개 이상의 파티션에 대해 스트라이프를 한다면, 성능 '이득' 은 음이 될 수도 있다 - 그렇게 하지 않도록 유의하라. 하나의 IDE 버스에 연결된 두개의 디스크로 스트라이핑을 하는 것 역시 쓸모없는 것으로 보인다 - 내가 기억 하는 것 이상으로 IDE 가 발전해오지 않은 한은 그렇다.
FIXME: 지금도 여전히 그럴까?
오래된 마더보드들은 두개의 IDE 버스를 갖고 있을 것인데, 두번째 버스는 느린 씨디롬 드라이브를 사용하는데 할당되었을 것이다. 여러가지의 툴을 이용해서 벤치마크를 수행할 수 있는데, 가장 주목할만한 것은 'Bonnie' 이다. ReiseFS 개발자들은 Bonnie++ 를 발표했는데 성능 자료를 측정하기 위해 사용할 수 있다.
많은 하이엔드 인텔 x86 서버들은 하드웨어 RAID 컨트롤러를 갖고 있다. 그것들의 대부분은 적어도 2개의 독립적인 SCSI 채널을 갖고 있다. 다행히도, 이것들은 LVM 에 거의 관계가 없다. Linux 가 그러한 컨트롤러에 관한 것을 알 수 있기 전에 관리자는 raid 컨트롤러 자체 안에서 논리적 드라이브를 결정해야 한다. 예를 들어 [ SCSI 채널 A에 있는 두개의 디스크를 스트라이프로 묶어서, 채널 B 에 있는 두개의 디스크에 그것들을 미러할 수 있다. 이것은 전형적인 성능과 데이터 안정성 을 최대화하는 전형적인 레이드 0/1 설정이다. 이렇게 설정된 시스템에서 리눅스가 부팅될 때 리눅스는 레이드 컨트롤러에 있는 오직 하나의 디스크만을 '볼' 수 있으 며, 이 디스크는 레이드 0/1 스트라이프셋에서 네개의 디스크를 포함하고 있는 논리적 드라이브이다. 이것은, LVM 에 관련해서는, 머신에 오직 하나의 디스크만 존재하며, LVM 에서도 역시 그렇게 사용됨을 의미한다. 만약 디스크중의 하나가 고장 나더라도, LVM 은 알지도 못할 것이다. 관리자가 디스크를 교체할 때(심지어 핫스왑 하드웨어를 가진 것을 즉시(on the fly) 교체하더라도), LVM 은 그것을 알지 못할 것이고, 컨트롤러가 미러된 자료를 재동기화(resync) 하고, 모든것이 좋은 상태로 돌아올 것이다. 이것은 대부분의 사람들이 한걸음 뒤로 물러서서 "그렇다면 이 레이드 컨트롤러를 이용하여 LVM 이 나에게 어떤 도움이 될까요?" 라고 물어보는 것이다. 간단한 답변은, 대부분의 경우에, 당신이 레이드 컨트롤러에서 논리적 드라이브를 정의한 이후에는, 더 이상의 디스크를 그 드라이브에 추가할 수 없다는 것이다. 그래서 만약 당신이 공간 요구량을 잘못 계산하거나 단지 더 많은 공간을 추가로 필요로 할 뿐이라면, 이미 존재하는 스트라이프셋에 새로운 디스크나 디스크의 집합 을 추가할 수 없다. 이것은 당신이 컨트롤러에서 새로운 레이드 스트라이프셋을 생성 해야 하고, 그 후에는 LVM 을 이용해서 단순히 LVM 논리 볼륨을 확장할 수 있으며, 따라서 빈틈없이 레이드 컨트롤러에 있는 두개의 스트라이프셋을 모두 확장하는 것을 의미한다.
리눅스 2.4에는 매우 훌륭한 레이드가 있다. 리눅스 2.2에서는 기본값으로, Alan Cox 에 의해 릴리즈 된 것에는, 잘 고려되지 않는 이전의 레이드 버전을 특징이다. 2.2 가 여전히 오래된 릴리즈를 특징으로 삼고 있는 이유는 커널 개발자들이 안정버전에서 사용자영역(userland) 업데이트를 필요로 하는 변화를 원하지 않기 때문이다.
Red Hat, Madrake, SuSE 를 포함한 대부분의 사람들은, 그것을 훨씬 좋아보이는 0.90 버전으로 교체하기로 결정했다.
이 모든 새로운 기법에서는, 한 머신에서 다른 머신으로 디스크를 옮기는 것과 같은 간단한 작업들이 까다로울 수 있다. 예전에는, LVM 사용자들은 오직 디스크를 새 머신에 장착하고 파일시스템을 마운트하기만 하면 되었다. LVM 에는 그것에 약간 더 해 해줘야 할것이 있다. LVM 스트럭쳐들은 디스크들과 /etc/lvmconf 디렉토 리에 모두 저장되므로 한개의 디스크 혹은 볼륨 그룹을 포함하는 디스크들의 집합을 이동하기 위해서 해야 하는 일은 오직 VG 가 속한 기계가 그것을 놓치지 않을 것인지 확인하는 것 뿐이다. 이것은 vgexport 명령을 통해 할 수 있다. vgexport 는 단순히 /etc/lvmconf 에서 VG 에 대한 스트럭쳐를 제거할 뿐이며, 디스크에 있는 것은 아무것도 바꾸지 않는다. 새로운 머신에 디스크가 장착되면, (그것들이 같은 ID 를 가질 필요는 없다) 해줘야 할 유일한 일은 /etc/lvmconf 를 갱신하는 것이다. 그것은 vgimport 를 통해 할 수 있다.
예제:
#1: 번 머신에서
vgchange -a n vg01
vgexport vg01
#2: 번 머신에서
vgimport vg01 /dev/sda1 /dev/sdb1
vgchange -a y vg01
볼륨 그룹에 대해 같은 이름을 사용할 필요는 없음에 주목하라. 만약 vgimport 명령이 설정 백업을 저장하지 않았다면 설정 파일을 저장하기 위해서는 vgcfgbackup 명령을 사용하라.
v0.9, 10 July 2000
이 문서에서는 TCP/IP 네트웍에서 멀티캐스트와 관련된 전반적인 사항을 설명한다. 따라서 상당부분 리눅스에 국한되는 내용이 아니다. (아직..GNU/리눅스를 쓰지 않을 경우에만) 멀티캐스트는 지금까지도 활발히 연구중인 분야이다. 따라서 이 글의 작성 시점에서는 표준안 대부분이 초안(draft)일 뿐이다. 이점 염두에 두고 읽으시기 바란다.
나는 이 문서에서 TCP/IP 네트웍에서 멀티캐스트에 대해 가능한 한 광범위하며 최신의 그리고 정확한 정보를 다루도록 노력할 것이다. 여러분의 어떠한 의견이라도 환영한다. 내용 중에 오류가 있거나 조언 및 추가할 내용이 있다면 저자에게 보내주기 바란다.
1.1 멀티캐스트(Multicast)란 무엇인가?
멀티캐스트는 곧 필요성이다. 만일 인터넷상의 여러-전체가 아닌-호스트에게로 전송해야할 상당한량의 정보를 가지고 있다면 바로 멀티캐스트가 그 해답이다. 예를 들어, 인터넷에 분산되어 호스트들로 원격 회의를 하기 위해 실시간으로 영상과 음성을 전송하는 경우, 멀티캐스트를 사용 할 수 있다.
멀티캐스트는 사용자가 자신의 수신기를 조정(관심 있는 채널의 주파수 선택)함으로서 정보를 받는다는 점에서 TV나 라디오와 유사하다. 다른 것은 제쳐두고 자신이원하는 것만 수신한다.
1.2 유니캐스트(Unicast)의 문제점
브로드캐스트(Broadcast)도 아니며 멀티캐스트도 아닌 것을 유니캐스트라 한다. 별로 좋지 않은 정의 같은데...패킷을 전송할 때 송신 프로세스 하나, 수신 프로세스 하나가 존재할 때 이것을 유니캐스트라 한다. TCP는 그 자체가 본질적으로 유니캐스트를 지향한다. 한편, UDP는 훨씬 다양한 형식을 가질 수 있지만 수신하는 프로세스가 단 하나일 때 이 역시 유니캐스트라 할 수 있다.
인터넷 초기에는 유니캐스트로 충분했었다. 1993년 4.4 BSD에서 최초로 멀티캐스트를 구현해서 세상에 내놓았을 때까지는 아무도 그것을 필요로 하는 것 같지 않았다. 그런데 왜 멀티캐스트라 불리는 것이 나오게 된 것일까?
말할 필요도 없이 인터넷은 초기의 모습으로부터 엄청난 변화를 겪었다. 특히 웹의 등장은 상황을 완전히 뒤바꾸어 놓았다. 사람들은 mail, FTP 그 이상의 것을, 자신들의 홈페이지에서 그림을 보기 원했고 더 나아가 음성과 동영상을 원했다.
오늘날의 기술이라면, 당신의 웹을 보고자하는 모든 이에게 유니캐스트 연결을 한다고 해도 충분히 그 "비용(cost)"를 감당할 수 있다. 하지만 음향이나 영상을 보내고자 한다면 엄청난 대역폭이 필요하다. 멀티캐스트를 고려에 넣는다면 두 가지 선택이 있다. 아니, 멀티캐스트가 등장하기 전까지는 두 가지 선택이 존재했었다. 유니캐스트를 통해 각 수신자별로 독립된 연결을 할 것인가, 아니면 브로드캐스트를 할 것인가.
전자는 부적절하다. 음성/영상의 단일 연결조차도 상당한 대역폭을 차지할 터인데 이러한 연결이 수백 또는 수천이라고 상상해 보라. 아마도 당신의 컴퓨터와 네트웍은 붕괴하고 말 것이다.
브로드캐스트가 해답인 듯 하지만 그것도 확신할 수가 없다. 우리 LAN에 있는 모든 호스트가 회의에 참석한다면 브로드캐스트가 확실히 해답이 될 수 있다. 모든 패킷은 한번씩만 전송되며 다른 모든 호스트는 브로드캐스트 주소를 통해 패킷을 수신할 것이다. 하지만, 문제는 일부 호스트만이 이 패킷에 수신하려할 경우다. 게다가, 정말로 회의에 참여하고자하는 단 하나의 호스트가 몇 개의 라우터를 거쳐야 도달 할 수 있는 외부 LAN에 존재한다면 어려운 문제가 된다. 알다시피, 브로드캐스트는 단일 LAN 내부에서만 가능한데, 브로드캐스트 패킷을 라우팅하여 외부 LAN에 전달할 방법이 없다.
최선의 해결책은 패킷을 -마치 TV나 라디오 채널처럼-일부 특정한 주소로만 보내는 것이다. 그러면 회의에 참여하고자하는 모든 호스트는 이 패킷이 네트웍을 통과할 때, 목적지 주소(destination address)를 감지하여 읽어들인 후 자신의 IP계층(layer)으로 보내어 복호화(demultiplexing)한다. 즉, 멀티캐스트는 패킷이 단 한번만 송신되어서 네트웍의 모든 호스트들이 그것을 읽는다는 점에서는 브로드캐스트와 같지만, 이 패킷들이 오직 커널(kernel)에서 원할 경우에만 읽고 처리한다는 점에서 브로드캐스트와 다르다.
이 특별한 패킷들은 IP 패킷이기 때문에 커널 수준(kernel level)에서 라우팅한다. 커널에 라우팅 경로를 알려주는 라우팅 알고리즘에 차이점이 있을 것이다.
Bit --> 0 31 Address Range:
+-+----------------------------+
|0| Class A Address | 0.0.0.0 - 127.255.255.255
+-+----------------------------+
+-+-+--------------------------+
|1 0| Class B Address | 128.0.0.0 - 191.255.255.255
+-+-+--------------------------+
+-+-+-+------------------------+
|1 1 0| Class C Address | 192.0.0.0 - 223.255.255.255
+-+-+-+------------------------+
+-+-+-+-+----------------------+
|1 1 1 0| MULTICAST Address | 224.0.0.0 - 239.255.255.255
+-+-+-+-+----------------------+
+-+-+-+-+-+--------------------+
|1 1 1 1 0| Reserved | 240.0.0.0 - 247.255.255.255
+-+-+-+-+-+--------------------+
우리가 주의 깊게 할 것은 "D 클래스 주소"다. 목적지 주소가 "1110"으로 시작하는 IP 데이터그램은 멀티캐스트 데이터그램이다.
나머지 28비트는 송신할 데이터그램의 멀티캐스트그룹을 구분하는데 쓰인다. 방송을 듣기 위해 라디오를 어떤 주파수에 맞추는 것과 유사하게 특정한 멀티캐스트 그룹으로 전송되어오는 패킷을 수신하기 위해서 우리의 커널을 특정한 그룹에 맞추어야 한다. 이 과정이 이루어 졌을 때, 호스트가, 지정한 인터페이스를 통해 그룹에 참여했다고 할 수 있다. 후에 더 자세히 다룰 것이다.
예약된 멀티캐스트 그룹(well known multicast groups)이라 불리는 특별한 그룹들이 있는데 이러한 그룹은 다음과 같은 특수한 용도로 쓰이기 때문에 개인적인 프로그램 제작 시에 사용할 수 없다.
224.0.0.1 은 전체 호스트 그룹이다. 멀티캐스트 인터페이스는 시동시 이 그룹에 참여해야하므로 이 주소로 ping을 보내면 모든 멀티캐스트 호스트들이 응답할 것이다.
224.0.0.2 은 전체 라우터 그룹이다.
224.0.0.4 은 전체 DVMRP 라우터 그룹이다.
224.0.0.5 은 전체 OSPF 라우터 그룹이다.
224.0.013 은 전체 PIM 라우터 그룹이다.
...
이 특수 그룹들은 모두 RFC문서 "Assigned Numbers"에 정기적으로 등록된다.
어떠한 경우든지, 224.0.0.0에서 224.0.0.225의 범위는 지역적인 목적(관리나 유지/보수)을 위해 예약되어 있으며 멀티캐스트 라우터들도 이 범위 내의 주소로 목적지로 하는 데이터그램은 포워딩하지 않을 것이다. 이와 유사하게 239.0.0.0에서 239.255.255.255의 범위는"administrative scoping"을 위하여 예약되어 있다. ("administrative scoping")에 관해서는 2.3.1을 참조할 것).
2.2 적응 단계(Levels of Conformance)
호스트가 만족해야하는 멀티캐스트 규격에는 세 가지 적응 단계가 있다.
Level 0 :the no support for IP Multicasting IPv4에서는 멀티캐스트가 의무적으로 구현해야하는 것이 아니기 때문에 인터넷에 있는 많은 호스트와 라우터들은 Level 0 상태에 있다. (하지만 IPv6에서는 의무적으로 멀티캐스트를 지원하도록 하고 있다.) 더 이상 설명은 필요 없다. 이 상태에 있는 호스트는 멀티캐스트 패킷을 보내거나 받을 수 없으며, 멀티캐스트 패킷을 완전히 무시한다.
Level 1 :the support for sending but not receiving multicast IP datagrams 따라서, 데이터그램을 보내기 위해서 멀티캐스트 그룹에 가입할 필요는 없다. Level 0 호스트를 Level 1 호환 상태로 만들기 위해서는 IP 모듈을 약간 변경해야 한다. 자세한 내용은 2.3에서 다룬다.
Level 2 : the full support for IP multicasting Level 2 호스트는 멀티캐스트 데이터그램 송신과 수신이 가능해야 한다. 또, 멀티캐스트 그룹에 참가하고 탈퇴할 수 있어야 하며 새로 갱신된 멀티캐스트 정보를 라우터에 알 릴 수 있어야 한다. 따라서, 호스트의 TCP/IP 스택에 인터넷 그룹관리 프로토콜 Internet Group Management Protocol (IGMP) 이 구현되어 있어야 한다.
2.3 멀티캐스트 데이터그램 전송
이상으로 미루어보아, 멀티캐스트 트래픽은 UDP로 트랜스포트 계층에서 처리하는 것이 분명하다. TCP는 점대점(point-to-point)연결을 제공하는 것이므로 멀티캐스트 트래픽에 적합하지 않다. (새로운 멀티캐스트 지향 트랜스포트 프로토콜 설계와 구현에 대한 연구가 활발히 진행중이다. 9장 "멀티캐스트 트랜스포트 프로토콜"을 참조할 것)
이론상, 응용프로그램에서 단지 UDP 소켓을 열고 class D 멀티캐스트 주소를 목적지로 하는 데이터그램을 부어넣기만 하면 된다. 그렇지만, 송신 프로세스가 통제권을 가지기 위해서 해주어야 할 작업이 있다.
TTL.
IP 헤더의 TTL(Time To Live) 필드는 멀티캐스트에서 중요한 의미를 가진다. 이 필드는 라우팅 에러로 인하여 데이터그램이 네트웍을 영원히 떠돌아다니는 것을 방지한다. 라우터는 네트웍간을 이동하는 데이터그램의 TTL 필드를 감소시키며 TTL 필드가 0이 되는 데이터그램은 버린다(drop). IPv4 멀티캐스트에서 TTL은 문턱값(threshold)의 의미를 지닌다. 다음 예를 보면 그 용도가 분명해진다.
우리 부서의 모든 호스트가 속하는 아주 길고 대역폭을 많이 차지하는 영상회의를 한다고 가정하자. 우리의 LAN에는 엄청난 용량의 트래픽이 발생할 것이며, 아마 우리 부서는 다양한 LAN이 존재하는 큰 네트웍일 것이다. 이 경우 우리는 LAN을 통하여 회의를 열기 원하지만, 우리의 멀티캐스트 트래픽 때문에 인터넷 전체가 붕괴되는 것을 원치 않을 것이다. 따라서, 멀티캐스트 트래픽이 라우터간을 얼마나 멀리이동할 수 있도록 할 것인지 제한할 필요가 있다. 이것이 TTL의 용도이다.
라우터는 각각의 인터페이스에 대해 TTL 문턱치(threshold)가 할당하고 있으며 이 문턱치보다 큰 TTL값을 가진 데이터그램만이 포워딩된다. 데이터그램이, 어떤 문턱치가 할당되어있는 라우터를 지날 때, TTL값이 문턱치만큼 감소되는 것이 아니라는 점에 주의하라. 오직 비교만이 이루어진다 (앞에서 언급했듯이 TTL은 데이터그램이 라우터를 지날 때마다 1씩만 감소된다).
다음 리스트에 TTL문턱치와 그에 해당되는 범위가 표시되어 있다.
----------------------------------------------------------------------
TTL Scope
----------------------------------------------------------------------
0 호스트 내부로 제한. 인터페이스로 출력되지 않음.
1 동일 서브넷으로 제한. 라우터는 포워딩하지 않음.
<32 동일 사이트(site), 단체나 부서로 제한.
<64 동일 지역(region)으로 제한.
<128 동일 대륙으로 제한.
<255 무제한. 전세계.
----------------------------------------------------------------------
"사이트(site)" 나 "지역(region)" 에 대한 정확한 정의는 없다. 그것은 이 제한을 가할 관리자에게 달려있다.
이 TTL기법은 모든 요구에 부응할 만큼 유연성을 제공하지 못하며, 특히 겹쳐지는 지역(overlapping regions)을 다루거나 지리적(geographic)이거나 위상적(topologic)적인 그리고 대역폭 제한적인 연결에는 적합하지 않다. 이러한 문제를 해결하기 위하여 1994년 administratively scoped IPv4 multicast regions 이 제정되었다 (D. Meyer's "Administratively Scoped IP Multicast" Internet draft 참조). 이것은 TTL을 이용하지 않고 IP 주소를 이용하여 범위제한(scoping)을 가한다. 239.0.0.0 에서 239.255.255.255까지의 IP주소가 이 관리용 범위제한을 위해 예약되어 있다.
루프백(Loopback)
전송 호스트가 Level 2 적응 단계에 있으며 데이터그램을 전송하는 그룹의 멤버로 참여하고 있을 때, 패킷 복사본이 루프백 된다. 이것은 네트웍 인터페이스 카드가 해당 네트웍 인터페이스가 자신이 네트웍으로 전송한 패킷을 네트웍으로부터 다시 읽어온다는 것이 아니라, IP 계층이 데이터그램을 인식하여 전송 전에 패킷을 IP 입력 큐에 복사해 넣는 것을 의미하며 이 기능은 기본 값(default)으로 설정되어 있다.
이러한 기능은 필요한 경우도 있고 그렇지 않을 경우도 있다. 따라서 전송 프로세스는 이 기능을 원한다면 켜거나 끌 수 있다.
인터페이스 선택
다수의 네트웍 인터페이스가 부착되어 있는 호스트에서는 응용 프로그램으로 하여금 어떤 인터페이스로 전송을 출력해야하는지 결정할 수 있도록 해 주어야한다. 만일 지정 값이 없다면 커널이 관리자의 설정에 기초하여 기본 값을 정한다.
2.4 멀티캐스트 데이터그램 수신
멀티캐스트 그룹 참여(Join)
브로드캐스트는 멀티캐스트보다 비교적 구현하기 쉽다. 브로드캐스트는 커널에 패킷 처리 규칙을 추가로 알려줄 필요가 없다. 커널은 브로드캐스트 패킷을 읽고 적절한 응용프로그램으로 전달하는 방법을 알고 있다.
그러나 멀티캐스트에서는 우리가 어떤 그룹에 관심이 있는지 커널에 알려줄 필요가 있다. 즉, 커널에 어떤 그룹에 "참여(join)@quot;하도록 요청해야 한다는 것이다. 하드웨어에 따라, 멀티캐스트 데이터그램을 하드웨어가 직접 필터링하거나 아니면 IP 계층에서 하는 경우도 있다. 어떤 경우에는 양쪽 모두에서 이루어지기도 한다. 오직 "참여 (join)"를 통해서 등록된 그룹만이 받아들여진다.
본질적으로 우리가 그룹에 참여한다는 것은 커널에게 다음과 같은 이야기를 하는 것을 의미한다. " 기본 설정으로 멀티캐스트 데이터그램을 처리하지 않는다는 것을 알고 있지만, 내가 이 멀티캐스트 그룹에 참여하고자 한다는 점을 기억해주기 바란다. 그러니 이 네트웍 인터페이스에서 보이는 패킷가운데, 이 멀티캐스트 그룹 주소를 목적지 필드에 포함하고 있는 멀티캐스트 데이터그램을 읽고 (나뿐만 아니라 그것에 관심을 가지고 있는 모든) 프로세스에게 전달해 주기 바란다. ".
고려할 것 : 우선 그룹에 단지 참여만 하는 것이 모든게 아니라는 점을 주목하라. 우리는 특정한 네트웍 인터페이스 상에서 그룹에 참여한다. 물론, 하나 이상의 인터페이스로 같은 그룹에 참여하는 것이 가능하다. 만일 인터페이스를 확실히 지정하지 않는다면 데이터그램이 전송될 때 라우팅 테이블에 의거하여 커널이 지정할 것이다. 또한, 하나 이상의 프로세스가 동일한 인터페이스로 동일한 멀티캐스트 그룹에 참여하는 것도 가능하다. 모든 프로세스들은 해당 인터페이스로 보내지는 데이터그램을 수신한다.
전에 언급했듯이, 모든 멀티캐스트 호스트들은 시동시에 전체 호스트 그룹에 참여하기 때문에 224.0.0.1 로 ping을 보내면 네트웍 내에서 모든 호스트들이 응답을 보낼 것이다.
끝으로, 프로세스가 멀티캐스트 데이터그램을 받기 위해서는 , 커널에게, 그룹에 참여한 후 데이터그램을 송신하는 포트를 묶도록(bind) 요청해야 한다. UDP 계층은 패킷을 해석(demultiplex)하기 위해 목적지 주소와 포트번호를 같이 사용하며 어떤 소켓으로 혹은 어떤 소켓들로 패킷을 보낼지 결정한다.
멀티캐스트 Group 탈퇴
프로세스가 멀티캐스트 그룹을 떠날 때는 커널에 그 그룹을 떠나고자 한다고 알린다. 이것이 커널이 그 그룹으로 오는 멀티캐스트 데이터그램을 더 이상 받지 않음을 의미하는 것이 아니라는 점을 이해해야 한다. 만일 "multicast join" 신청을 제출한 프로세스가 더 있고 그 그룹에 여전히 관심을 가지고 있는 상태라면 커널은 여전히 패킷을 수신할 것이다. 이러한 경우 호스트는 모든 프로세스가 그 그룹을 떠나기로 결정할 때까지 여전히 그룹에 남아 있게된다.
추가 : 그룹을 떠난다 할지라도, 수신하던 포트에 여전히 연결(bind)된 채로 남아있을 것이며 아직 멀티캐스트 그룹에 참여하고 있는 프로세스가 더 있으면 멀티캐스트 traffic을 계속 수신하게 될 것이다.
멀티캐스트 group 에 참여함에 있어서, 요점은 IP 와 data link 계층에 해당 그룹으로 향하는 멀티캐스트 데이터그램을 받도록 지정하는 것이다. (경우에 따라서는 명시적으로 하드웨어에 지정하는 경우도 있다) 이것은 프로세스 단위(per-process membership)가 아니라 호스트 단위(per-host membership)이다.
IP 멀티캐스트 주소에서 Ethernet/FDDI 주소로의 사상(mapping)
Ethernet과 FDDI 에서 프레임(frames)은 48 비트의 목적지 주소공간을 가진다. 멀티캐스트 IP 주소를 ethernet/FDDI로 사상하기 위한 멀티캐스트 ARP 같은 것을 피하기 위해서, IANA는 멀티캐스트를 위해 주소공간을 예약했다. 목적지가, 01-00-5e-00-00-00 에서 01-00-5e-ff-ff-ff (16진수)사이의 모든 ethernet/FDDI 프레임은 멀티캐스트 그룹을 위한 데이터를 가진다. 접두어(prefix) 01-00-5e 는 해당 프레임이 멀티캐스트 임을 나타내며, 바로 다음 비트는 항상 0이다. 따라서, 나머지 23 비트만이 멀티캐스트 주소를 위해 사용된다. 그런데, 멀티캐스트 그룹의 IP는 28비트 길이이므로 1대1 사상은 불가능하다. 오직 IP 멀티캐스트 그룹의 23개 하위 비트(Least Significant Bit)만이 프레임에 위치한다. 남는 5개의 상위 비트는 무시되며32개의(2^5=32) 서로 다른 멀티캐스트 그룹이 동일한 ethernet/FDDI address사상된다. 이것은 ethernet 계층이 완전한 필터로 작용하지 못함을 의미하며, IP 계층이 data link 계층을 통과해온 데이터그램을 받을 것인지 버릴 것인지를 결정해야 할 것이다. IP 계층이 최후의 완벽한 필터이다.
FDDI상의 IP 멀티캐스팅에 관한 자세한 내용은 RFC 1390 "Transmission of IP and ARP over FDDI Networks" 에 나와있다. IP Multicast 주소의 ethernet으로의 사상에 관한 더욱 자세한 내용은 draft-ietf-mboned-intro-multicast-03.txt "Introduction to IP Multicast Routing"을 참조하라.
Token-Ring LAN 상에서의 IP 멀티캐스트에 관심이 있다면 RFC 1469를 참조하라.
Linux는 당연히(설마 의심을?) 완전한 Level 2 멀티캐스트를 지원한다. 모든 송수신 요구사항을 만족하며 멀티캐스트 데이터그램에 관해서 라우터(mrouter)처럼 작동한다.
멀티캐스트 송수신이 하고싶다면 커널 설 정시 "IP: multicasting"에 yes라고 해주기만 하면 된다. Linux box를 멀티캐스트 라우터 (mrouter)로 사용하고 싶다면 "IP: forwarding/gatewaying", "IP: multicast routing" 그리고 "IP: tunneling"을 선택해주면 된다. 후자는 새로운 버전의 mrouted가 멀티캐스트 데이터그램을 유니캐스트 데이터그램에 캡슐화(encapsulation)해서 보내기 위해 IP tunneling 에 의존하기 때문이다. 이것은 유니캐스트 전용 네트웍에 분산되어있는 멀티캐스트 호스트들간의 연결(tunneling)을 위해서 필요하다. (mrouted는 라우팅 알고리즘-라우팅 정책-을 구현하고 커널에 멀티캐스트 데이터그램을 어떻게 라우팅할 것인지 알려주는 daemon이다).
어떠한 버전의 커널들은 멀티캐스트 라우팅을 "EXPERIMENTAL"로 분류하고 있기 때문에, "Code maturity level options"섹션에서 "Prompt for development and/or incomplete code/drivers"옵션을 가능하게 해 주어야 한다. 만일 mrouted가 실행중일 때 우리의 Linux box가 속해있는 동일 네트웍에서 생성된 traffic은 정상적으로 다른 네트웍에 포워딩해주는데, 다른 네트웍의 traffic을 볼 수 없다면 ICMP 에러메시지를 받고있지는 않는지 확인해 보라. 거의 모든 경우가 IP tunneling을 활성화 시켜놓지 않은 경우 일 것이다. 일단 알고나면 정말 간단한 것이지만, 정말이지, 모르는 경우에는 시간 꽤나 걸리고 이유도 쉽사리 알기 어렵다. 이런 상황에서는 스니퍼(sniffer)가 정말 유용하다!
(멀티캐스트 라우팅에 대해서는 "Routing Policies and Forwarding Techniques" 섹션에서, mrouted 와 tunnel 에 대해서는 "The MBone" 과 "Multicast applications"에서 추가로 설명한다).
일단 커널을 컴파일하고 설치한 후에는 멀티캐스트 트래픽을 위한 기본 라우팅경로를 설정 해야한다. 우리의 목표는 224.0.0.0 네트웍으로의 경로를 추가하는 것이다.
대부분의 사람들이 이 단계에서 겪는 무제는 마스크 값으로 인한 어려움이다. 만일 Terry Dawson의 유명한 NET-3-HOWTO를 읽었다면, 올바른 값을 알아 맞추기 어렵지 않을 것이다. 그 문서에서 설명했듯이, 넷마스크(subnetmask)는 우리의 IP 주소의 네트웍 부분을 모두 1로 채우고 호스트 부분을 모두 0으로 채운 32비트 숫자이다. 섹션 2.1에서 보았듯이 클래스D 멀티캐스트 주소는 네트웍/호스트형식으로 구분되어있지 않다. 대신 18비트의 그룹 구분자와 4비트의 클래스D 구분자로 이루어져있다. 이 4비트가 네트웍 부분에 대응되고 28비트가 호스트 부분에 대응된다. 따라서 서브넷마스크는 11110000000000000000000000000000 쉽게 읽자면, 240.0.0.0이 된다. 그러면 완전한 명령어는 다음과 같이 될 것이다.
route add 224.0.0.0 netmask 240.0.0.0 dev eth0
route 프로그램의 버전에 따라서 add뒤에 -net 을 붙여야 하는 경우도 있다.
여기서 eth0이 멀티캐스트 가능하다고 가정했으며, 달리 지정되지 않을 경우 멀티캐스트 트래픽이 eth0으로 출력될 것이다. 이것이 우리에게 해당되지 않는다면 dev 변수 값을 다른 값으로 바꾸어 주어야한다.
여기서 다시 한번 /proc 파일시스템의 유용성이 입증된다. 우리는 우리호스트가 참여하고 있는 그룹을 /proc/net/igmp를 통해서 확인해 볼 수 있다.
장점과 함께 단점도 있는 기술이다. 나의 사견이지만, 장점은 분명하다는 점이다. 주된 단점은 아직 수백의 호스트들, 특히 라우터들이 아직 지원하지 않고 있다는 점이다. 결과적으로 멀티캐스트를 사용하는 사람들은 새로운 장비를 구입하고 운영체제를 수정하며 자신의 장소에 멀티캐스트라는 섬을 만든다. 그리고 그들은 다른 곳에서 자신과 비슷한 일을 하고 있는 사람들과 통신할 수없음을 알게된다. 그들 사이의 멀티캐스트를 지원하지 않는 단 하나의 라우터 때문에...
해답은 분명하다. 그들은 가상 멀티캐스트 네트웍을 인터넷 최 상단에 만들기로 결정한다. 즉 멀티캐스트 라우터를 가진 사이트들은 그들간에 직접적으로 통신하는 것이다. 하지만 유니캐스트 라우터를 통해서 연결된 사이트들은 다른 멀티캐스트 섬으로 유니캐스트 갭슐화된 멀티캐스트 트래픽을 보내야 할 것이다. 중간에 걸쳐진 라우터들-유니캐스트전용 라우터들-은 유니캐스트 트래픽을 다루는 것이 되므로 문제가 되지 않는다. 끝으로 수신 측에서는 캡슐화된 트래픽을 다시 원래의 멀티캐스트 트래픽으로 해석할 것이다. 이렇게 멀티캐스트 트래픽을 유니캐스트 트래픽으로 다시 멀티캐스트 트래픽으로 변환하는 것을 멀티캐스트 터널링(tunneling)이라 한다.
즉, MBone 또는 멀티캐스트 백본(Multicast Backbone)은 멀티캐스트 섬들을 멀티캐스트 터널로 이어주는 가상 멀티캐스트 네트웍(virtual multicast network)이다.
이 MBone에 관한 활동들이 활발하다. 그러한 반면 지금도 인터넷에서는 실시간 오디오 및 비디오로 풍부한 원격회의가 이루어지는 중이다. 최근 Linus Torvalds가 Silicon Valley Linux Users Group에서 발표한 것이 라이브로 인터넷 전송된 일이 있다.
멀티캐스트를 다루는 대부분의 사람들은 조만 간에 MBone에 연결할 것이며 mrouted를 필요로 할 것이다. 우리 역시 멀티캐스트라우터가 없는 상태에서 다른 서브넷으로 멀티캐스트 트래픽을 전달하기 원한다면 mrouted가 필요하다. mrouted는 멀티캐스트 데이터그램을 유니캐스트 형식으로 캡슐화하여 (IP에서 IP로) 유니캐스트 라우터를 통해 멀티캐스트 트래픽을 전송할 수 있도록 해주며, 이 외에도 몇 가지 기능이 있다. 가장 중요한 것은 멀티캐스트 데이터그램의 발신지와 목적지를 감지하여 어떻게 라우팅을 할 것인지 아니면 하지 않을 것인지 커널에 알려준다는 점이다. 멀티캐스트 라우터를 가지고 있다고 하더라도 mrouted는 커널에 데이터그램으로 무엇을 할지 알려준다. (어떻게가 아니라 무엇이다. mrouted는 "이것을 저 인터페이스가 연결된 네트웍으로 포워딩하라."고 말하지만, 실제로 포워딩은 커널이 수행한다.) 실제 포워딩 작업 부분(어디서 할 것인가)과 포워딩 알고리즘 부분(어떻게 할 것인가)을 구분하면 포워딩 코드를 오직 한번만 작성해서 커널에 넣으면 되기 때문에 아주 유용하다. 포워딩 알고리즘과 정책은 추후에 사용자 공간의 데몬(user space daemon)에서 구현되며, 따라서, 커널을 재 컴파일 할 필요 없이 라우팅 정책을 쉽게 수정할 수 있다.
다음으로 리눅스로 포팅된 멀티캐스트 응용프로그램들 가운데 MBone에 연결하도록 작성된 것들에 대해 알아본다. 여기에 있는 리스트는 Michael Esler의 "Linux Multicast Information"에서 가져왔다. http://www.cs.virginia.edu/~mke2e/multicast/. 멀티캐스트와 리눅스에 대한 정보가 아주 많아 추천할 만 하다.
약간 설명할 필요가 있어서 이것들은 뒤에 놓았다. 회의를 하게되면 회의를 위한 서비스들(음성, 영상, 공유 칠판, 등등...)에 멀티캐스트 그룹과 포트들을 할당한다. 회의를 시작하면 멀티캐스트 그룹과 포트, 프로그램(vic, vat, ...)등에 관한 정보가 주기적으로 MBone으로 전송된다. 회의 도구들은 이러한 정보를 "듣고 "우리가 관심 있는 회의가 언제 있는지 (혹은 있을지) 알아보기 쉽게 알려준다. 또한, 회의에 참여하는 과정을 쉽게 해준다. 프로그램을 실행시켜서 참여할 그룹/포트번호를 알려주는 대신 클릭하는 것만으로 세션도구들이 적절한 프로그램을 실행시키고 그 프로그램에 적절한 정보를 제공한다. 회의도구들은 보통 사용자 자신의 회의를 MBone에 알리는 역할도 한다.
멀티캐스트를 지원하기 위해서 몇 가지 확장된 응용 프로그래밍 인터페이스(API)가 필요하다. 그 가운데 대부분은 setsockopt() (커널에 정보를 전달함) 와 getsockopt() (멀티캐스트 관련 정보 구함) 두 가지 시스템 호출을 통해 처리한다. 새로운 시스템 호출 두개가 멀티캐스트를 지원하기 위해 추가되었다는 뜻이 아니다. setsockopt()/getsockopt()는 4.2 BSD 시절부터 있었다. 단지 커널에 전달해 주어야하는 새로운 멀티캐스트 옵션이 추가되었을 뿐이다.
setsockopt()/getsockopt() 함수의 선언이다.
int getsockopt(int s, int level, int optname, void* optval, int* optlen);
int setsockopt(int s, int level, int optname, const void* optval, int optlen);
첫 번째 변수 s는 시스템 호출을 적용할 소켓이다. 멀티캐스트에서 이 소켓은 AF_INET 계열 이어야하며, 소켓 타입은 SOCK_DGRAM 또는 SOCK_RAW를 쓸 수 있다. 대부분은 SOCK_DGRAM으로 쓰지만, 라우팅 데몬을 제작하거나 수정할 계획이라면 SOCK_RAW 이 필요할지 모른다.
두 번째 변수 level은 옵션이나, 질의(query), 메시지(message)를 처리할 레이어를 의미한다. 소켓 레이어는 SOL_SOCKET, IP 레이어는 IPPROTO_IP, 등등이다. 멀티캐스트 프로그래밍에 level은 항상 IPPROTO_IP 이어야 한다.
optname은 우리가 설정 값을 지정하는 것인지 얻으려 하는 것인지를 의미한다. 설정 값 자체는(커널에 설정하거나 커널로부터 읽어오는 두 경우 모두) optval이다. 멀티캐스트 프로그래밍에서 optnames는 다음과 같다.
optname setsockopt() getsockopt()
IP_MULTICAST_LOOP yes yes
IP_MULTICAST_TTL yes yes
IP_MULTICAST_IF yes yes
IP_ADD_MEMBERSHIP yes no
IP_DROP_MEMBERSHIP yes no
optlen은 optval이 가리키는 데이터구조의 크기를 의미한다. 단, getsockopt()에서는 반환 값이 된다. 커널은 optname 값을 optval이 가리키는 버퍼에 써넣은 후 optlen을 통해 자료의 크기를 알려준다.
setsockopt()/getsockopt()모두 실행 결과 성공하면 0, 에러가 발생하면 -1을 반환한다.
6.1 IP_MULTICAST_LOOP.
프로그래머라면, 데이터를 호스트로 루프백 시킬 것인지 결정해야한다. 만일, 프로세스가 여러 개이거나 데이터를 리스닝"listening"중인 사용자가 있다면 루프백을 가능하게 해야한다. 하지만, 카메라 이미지를 전송하는데 자기 화면에서 이미지를 볼 필요가 없다면, 아마도 루프백이 필요 없을 것이다. 후자의 경우 프로그램은 컴퓨터에 부착된 카메라로부터 영상자료를 이미 가지고 있을 것이기 때문에, 다시 소켓으로부터 자료를 받기 원하는 경우는 드물 것이다. 루프백은 기본 값으로 활성화되어 있다.
특별히 지정하지 않는다면, 멀티캐스트 데이터그램은 지역 네트웍 외부로 전송되는 것을 방지하기 위해 TTL 1을 기본 값으로 전송된다. TTL을 원하는 값으로(0에서 255까지) 바꾸기 위해서 TTL값을 변수에 넣고 프로그램에서 다음과 같이 써주면 된다.(여기서는 "ttl"이라고 했다.)
이후부터 이 소켓에서 생성된 모든 멀티캐스트 트래픽은 위에서 선택한 인터페이스로 출력된다. 원래 설정을 회복하여 관리자의 설정을 무시하고 커널이 외부 출력 인터페이스를 선택하도록 하려면 인터페이스에 INADDR_ANY를 설정하고 위와 동일한 옵션으로 setsockopt()를 호출한다.
외부 출력 인터페이스를 선택함에 있어서, 다음 ioctl이 유용할 것이다. SIOCGIFADDR (인터페이스 주소 얻기), SIOCGIFCONF (전체 인터페이스 목록 얻기), SIOCGIFFLAGS (인터페이스 상태 플래그(flag)를 얻어서 인터페이스가 멀티캐스트 가능한지 확인 - IFF_MULTICAST 플래그-).
호스트가 멀티캐스트 라우터로 작동한다면, 여러 인터페이스를 가지고 있거나 IP_MULTICAST_IF옵션이 설정되어 있지 않을 경우, 다른 인터페이스에서 멀티캐스트 포워딩이 가능하더라도 멀티캐스트는 기본 인터페이스를 통해 이루어진다.
6.4 IP_ADD_MEMBERSHIP.
커널에 우리가 어떤 그룹에 관심이 있는지 알려주어야 한다고 했던 것을 다시 생각해 보자. 그룹에 관심 있는 프로세스가 하나도 없다면, 그 그룹을 향해서 전송되어오는 패킷은 모두 폐기된다. 따라서 커널에 우리의 관심 그룹을 알리고, 그룹의 회원(member)이 되기 위해서는 다음과정이 필요하다. 우선 ip_mreq 구조체의 내용을 채운다. 그리고, optval을 설정하여 setsockopt()를 호출해서 커널에 이 구조체를 넘겨주면 된다.
ip_mreq 구조체는 (/usr/include/linux/in.h에 있음) 다음과 같다.
struct ip_mreq
{
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
주의 : 이 구조체의 "물리적" 정의는 위의 파일에 명시되어 있다. 하지만, 코드의 이식성을 위해서 <linux/in.h>을 포함(include)시켜서는 안 된다. 대신 <linux/in.h>를 포함하는 <netinet/in.h>을 포함시켜라.
첫 번째 멤버, imr_multiaddr는 우리가 참여할 그룹주소를 말한다. 회원(membership)은 그룹뿐만 아니라 인터페이스에도 관련이 있다는 점을 명심해야한다. 따라서, 두 번째 멤버, imr_interface값도 알려주어야 한다. 우리가 분산된 호스트에 있더라도 이러한 방식으로 각기 다른 인터페이스를 이용하여 같은 그룹에 참여할 수 있다. imr_interface는 와일드카드 주소(INADDR_ANY)를 이용할 수 있으며 이 경우 인터페이스를 선택하는 일은 커널이 한다.
일단 이 구조체를 채우면 (struct ip_mreq mreq;로 정의 했다고 하면) 다음 방법으로 setsockopt()를 호출하면 된다.
이 절의 목적은 멀티캐스트가 어떻게 작동하는지를 이해하는데 필요한 정보를 제공하는 것 도 아니고 멀티캐스트 프로그래밍에 대한 정보를 제공하자는 것도 아니다. 하지만 멀티캐스트의 기반을 이루는 프로토콜과 구현을 살펴봄으로서 쉽게 저지르는 실수와 잘못된 이해를 피할 수 있을 것이다.
7.1 IGMP.
IP_ADD_MEMBERSHIP 과 IP_DROP_MEMBERSHIP에서 이 명령으로 커널에 제공한 정보는 어떤 멀티캐스트 데이터그램을 받고 어떤 것을 버릴 것인지를 결정하는데 쓰인다고 했다. 맞는 말이라고 할 수 있지만, 모두 맞는 말은 아니다. 이러한 일반화는 전 세계 모든 멀티캐스트데이터그램이 우리의 호스트로 전달된 후, 호스트에서 프로세스가 발행한 회원관계를 확인 후 데이터그램의 폐기 여부를 결정한다는 말이 된다. 생각할 필요도 없이, 이것은 엄청난 대역폭 낭비임을 알 수 있다.
실제로는 호스트가 자신의 라우터에게, 그 라우터는 상위 라우터에게, 그리고 그 상위 라우터에게....어떤 멀티캐스트 그룹에 관심이 있는지 알려준다. 멀티캐스트 그룹 트래픽을 받을 것인지 말 것인지 결정하는 알고리즘 자체에는 상당히 변화가 심한데, 단 한가지 변하지 않는 것이 있다면, 이 정보를 전달하는 방법이다. 이것은 IGMP(Internet Group Management Protocol을 이용한다. 프로토콜번호 2인 IGMP는 ICMP와 유사한 새로운 프로토콜인데 IP 데이터그램을 이용하며 레벨 2 적응단계의 호스트는 이 프로토콜을 의무적으로 구현해야 한다. 전술한 바와 같이 이것은 라우터에게 회원정보를 전송하는 호스트와 라우터사이의 통신 양쪽 모두 사용한다. 다음 글에서 호스트-라우터간 관계만을 설명하기로 한다. 왜냐하면 mrouted소스 코드를 제외하고는 라우터-라우터간 통신을 해설하는 자료를 찾지 못하였기 때문이다. (RFC 1075-Distance Vector Multicast Routing Protocol은 이제 사용하지 않으며, mrouted는 아직 문서화되지 않은 변형된 DVMRP를 구현하고 있다.)
RFC 988-IGMP 버전 0은 이제 사용하지 않는다.
IGMP 버전 1은 RFC-1112에 정의되어 있고, RFC-2236 (IGMP version 2) 에서 개정되어 현재까지 많이 사용하고 있다. 리눅스 커널에서는 IGMP 버전 1 전체와 버전 2일부가 구현되어 있다.
지금부터 이 프로토콜에 대한 약식설명을 보자. RFC-2236을 펼쳐 놓고 정확한 정식 설명을 보는 것도 좋다.
IGMP 버전 1 (이하 IGMPv1) 는 전송시 "Max Resp Time" 을 "Unused",즉 모두 0 으로 하고 수신시에는 무시한다. "Type"란은 4비트 폭으로 나누어 "Version"과 "Type"으로 사용한다. IGMPv1 에서는 "회원질의(Membership Query)"를 0x11 (version 1, type 1)으로 확인하고, IGMPv2 에서는 0x11 로 확인하기 때문에 8비트를 사실상 동일하게 해석 한다.
IGMPv2 는 주로 추가사항들로 이루어져 있기 때문에 IGMPv1 을 일단 설명한 후 IGMPv2 추가사항을 설명하는 편이 좋을 것 같다.
다음 논의에서 라우터는 모든 IP 멀티캐스트 데이터그램을 받는다는 것을 기억하라.
7.2 IGMP version 1.
라우터는 주기적으로(1분에서 2분에 한번씩) TTL값 1의 IGMP 호스트 회원 질의를 전체 호스트 그룹(224.0.0.1)으로 보낸다. 모든 멀티캐스트 호스트들이 이 메시지를받지만 IGMP 호스트 회원 보고(Host Membership Report)가 폭주(storm)하는 것을 방지하기 위해 즉시 응답하지 않는다. 대신 질의를 수신한 인터페이스에 속하는 각 그룹에 대해, 임의 지연 타이머를 시작한다.
조만 간에 타이머가 완료되면 호스트는 역시 TTL 1의 IGMP 회원 보고를 멀티캐스트 그룹어드레스로 전송한다. 이 메시지는 이미 그룹에 참여하고 있는 모든 호스트들과 타이머가 완료되기를 기다리고 있는 호스트들에게 전달된다. 그러면 각 호스트들은 타이머를 중지하고 더 이상 아무런 보고도 하지 않는다. 하지만 이것으로 라우터는 자신의 서브넷에 그 멀티캐스트 그룹의 멤버가 존재한다는 것만 알면 되기 때문에 회원이 몇이나 있는지 알기 위해 더 이상, 보고 받을 필요가 없다.
몇 번 질의한 후에도 그 그룹에 대해 아무런 회원 보고가 없으면 라우터는 멤버가 없는 것으로 간주하고 해당 그룹의 트래픽을 서브넷으로 포워딩하지 않는다. IGMPv1 에서는 "그룹 탈퇴 메시지(Leave Group messages)"가 없다는 점에 주목하라.
호스트가 새 그룹에 참여하면 커널은 그룹으로 보고를 보내기 때문에 각각의 프로세스들은 새로운 회원 질의가 도착할 동안(1,2분 정도) 기다릴 필요가 없다. "IP_ADD_MEMBERSHIP" 정에서 보았겠지만, 이 IGMP 패킷은 IP_ADD_MEMBERSHI명령에 대한 응답으로 커널이 생성한다. "새 그룹"이라는 말을 주의 깊이 보자. 호스트가 이미 참여중인 그룹에 대해 프로세스가 IP_ADD_MEMBERSHIP 명령을 보낼 경우 우리는 이미 그 그룹의 트래픽을 받고 있기 때문에 아무런 IGMP 패킷도 만들어지지 않을 것이다. 대신 그룹사용 카운터가 증가한다. IGMPv1에서 IP_DROP_MEMBERSHIP 명령은 데이터그램을 생성시키지 않는다.
호스트 회원 질의는 타입 0x11, 호스트 회원 보고는 각각 타입 0x12로 구분한다.
전체 호스트 그룹에는 보고하지 않는다. 이 그룹으로의 회원은 영구적이다.
7.3 IGMP 버전 2.
상기 내용에 대한 추가 사항 중 중요한 것 한가지는 그룹 이탈 메시지(타입0x17)가 포함되었다는 사실이다. 이 메시지는 서브넷에서 마지막 호스트가 그룹을 이탈하는 시점과 질의 시간이 만료되어 라우터가 더 이상 그룹에 남아있는 회원이 없다고 결정하는 시점 사이의 대역폭 낭비(이탈 지연-leave latency)를 줄이기 위해 추가되었다. 그룹 이탈 메시지는 그룹의 다른 멤버들에게는 불필요한 정보이기 때문에 남아있는 그룹보다 전체 라우터 그룹(224.0.0.2)쪽으로 전송해야 한다. (커널 버전 2.0.33 이하에서는 이 메시지를 그룹으로 보냈었다. 호스트로서는 해를 입을 일은 없지만, 쓸데없는 정보이기 때문에 이 정보를 처리하는 것은 시간낭비일 뿐이다.) 언제 이탈 메시지를 보낼 것인가, 언제 보내지 않을 것인가 하는 문제에 대해서는 몇 가지 미묘한 문제가 있다. 관심이 있다면 RFC를 참조할 것.
IGMPv2라우터가 이탈 메시지를 받으면 라우터는 그룹을 지정하여(group-specific) 남아있는 그룹에게 질의를 보낸다. 이것도 IGMPv2 에서 추가된 사항이다. IGMPv1에서 그룹 지정 질의는 없었다. 모든 질의가 전체 호스트 그룹으로 보내는 질의였다. IGMP 헤더에 정의된 타입 값은 변하지 않았지만(전과 동일하게 0x11), "그룹 주소(Group Address)"필드는 남아있는 멀티캐스트 그룹 주소로 채워진다.
IGMPv1에서 전송시 0으로 채우고 수신시 무시하기로 하였던 "Max Resp Time" 필드는 "Membership Query"에서만 의미가 있다. 이 필드는 보고해야할 한계 시간을 설정하는데 쓰인다. 성능을 조절하는 메커니즘으로 사용한다고 볼 수 있다.
IGMPv2에서 새로운 메시지 타입 0x16이 추가되었다. 이것은 "Version 2 Membership Report"로서 IGMPv2 호스트가 IGMPv2 라우터를 발견했을 때 전송한다. (IGMPv2 호스트는 "Max Response" 필드가 0 으로 채워진 패킷을 확인하여 IGMPv1 라우터가 존재한다는 것을 알아낸다).
동시에 여러 라우터가 질의를 할 때, IGMPv2 는 "discussions"를 회피하는 메커니즘을 제공한다. 이 경우 낮은 IP 주소를 가진 라우터가 질의자(querier)가 되고 다른 라우터는 타이머를 설정한다. 낮은 번호의 라우터가 어떤 이유로 제대로 작동하지 못하면 타이머가 만료된 후 다시 질의자를 설정한다.
7.4 커널 관련 사항
이 절에서는 리눅스 커널에서 멀티캐스트 구현을 학습하기 위한 실마리를 보여줄 것이다. 구현 자체를 설명하지는 않는다. 단지 어디서 찾을 것인지만 알려주다.
이 내용은 2.0.32에서의 설명이므로 이 글을 읽는 시점에서 좀 오래된 내용일지도 모른다. (네트웍 코드는 2.1.x에서 많이 변경되었다.
리눅스 커널에서 멀티캐스트 코드는 항상 #ifdef CONFIG_IP_MULTICAST / #endif 쌍으로 둘러싸여 있기 때문에 필요하다면 언제든지 커널에 포함(inclusion/exclusion)시키거나 배제시킬 수 있다. (이 포함/배제는 컴파일 시에 행해지며 #ifdef 구문은 선행처리기가 하는 작업이라는 것을 알고 있을 것이다. 포함여부 결정은make config, make menuconfig 또는 make xconfig를 실행시킬 때 할 수 있다.)
멀티캐스트 라우터 기능을 사용하고 싶다면 #ifdef CONFIG_IP_MROUTE / #endif쌍 속의 코드들을 활성화 시켜야 한다.
커널 소스는 보통 /usr/src/linux에 있다. 하지만 위치는 변할 수도 있는 것이기 때문에 커널 소스의 위치를 간단 명료하게 LINUX라고 가정하자. 이제 커널소스를 /usr/src/linux 에 풀었을 경우, LINUX/net/ipv4/udp.c 는 /usr/src/linux/net/ipv4/udp.c 를 의미한다.
사용자 프로그램에서의 멀티캐스트 인터페이스는 멀티캐스트 프로그래밍을 설명한 절에서 setsockopt()/ getsockopt()를 통해 모두 보여 주었다. 이 두 함수는 전달받은 변수의 유효성을 검사한 다음, 다른 몇 가지 함수를 호출하여 추가 적으로 검사하고, 또 다른 함수를 호출하는 식으로 구현되었다. (이 모든 함수 호출에 관심이 있다면 LINUX/net/socket.c (함수 sys_socketcall() 와 sys_setsockopt()), LINUX/net/ipv4/af_inet.c (함수 inet_setsockopt()) 그리고 LINUX/net/ipv4/ip_sockglue.c (함수 ip_setsockopt()) 를 참조하라.)
LINUX/net/ipv4/ip_sockglue.c도 주의 깊게 보아야 한다. 여기에는 함수 ip_setsockopt() 와 ip_getsockopt() 가 들어 있는데 대부분은 (어떤 에러 체크 후에) 가능한 optname을 검사하는 스위치같은 것이다. 유니캐스트 옵션과 함께, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IP_MULTICAST_IF, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP같은 모든 멀티캐스트 옵션을 처리한다. 이 스위치 이전에 옵션을 검사하여 그것이 멀티캐스트 라우터 지정 옵션이라면 함수 ip_mroute_setsockopt() 와 ip_mroute_getsockopt() 로 라우팅 된다. (파일 LINUX/net/ipv4/ipmr.c 에 있음).
LINUX/net/ipv4/af_inet.c 에서 이전 절에서 논의했던 소켓 생성 기본 값을 볼 수 있다. (loopback enabled, TTL=1, 함수 inet_create() 중에서)
다음 코드가 "소켓을 닫으면 커널은 이 소켓에 있던 모든 회원을 탈퇴시킨다"는 내용을 단정적으로 보여준다. (위와 동일 파일의 함수 inet_release()에서)
#ifdef CONFIG_IP_MULTICAST
/* Applications forget to leave groups before exiting */
ip_mc_drop_socket(sk);
#endif
링크 계층의(Link Layer)의 장치 독립적인(Device independent) 연산들은 LINUX/net/core/dev_mcast.c 에 있다.
아직 두 가지 중요한 함수들을 설명하지 않았다. 입력 처리 함수와 멀티캐스트 데이터그램 출력 함수이다. 다른 데이터그램들과 마찬가지로 입력 데이터그램은 장치 드라이버로부터 ip_rcv() 합수(LINUX/net/ipv4/ip_input.c)로 전달된다. 이 함수에서 하위 계층으로부터 전해진 멀티캐스트 패킷을 완벽하게 필터링한다(하위레이어에서 최대한 필터링하지만, IP 계층에서 우리가 관심을 가지고 있는 그룹에 대해 100% 알고 있기 때문에 패킷을 완전하게 필터링한다고 했던것을 기억하자.) 호스트가 멀티캐스트 라우터로 작동중이라면 역시 이 함수가 패킷 포워딩 여부를 결정하고 적절하게 ipmr_forward()를 호출한다. (ipmr_forward() 은 LINUX/net/ipv4/ipmr.c에 구현되어 있다.).
패킷 출력 임무를 맡은 코드는 LINUX/net/ipv4/ip_output.c에 담겨져 있다. 이곳에서 패킷을 루프백 할지 안 할지(안한다면 ip_queue_xmit()호출) 검사하기 때문에IP_MULTICAST_LOOP 옵션이 효력을 발휘하는 곳이다. 또한, 외부로 향하는 패킷이 멀티캐스트인지 유니캐스트인지에 의거하여 TTL을 정하는 곳이기도 하다. 전자의 겨우 IP_MULTICAST_TTL 로 전달된 변수를 사용한다(함수 ip_build_xmit()).
mrouted(커널에 멀티캐스트 데이터그램 라우팅 방법을 알려주는 프로그램)로 작업하는 동안, 우리는 멀티캐스트 라우터로 작동하는 우리의 리눅스 박스에서 만들어진 패킷을 제외한, 로컬 네트웍에서 생성된 멀티캐스트 데이터그램은 모두 적절하게 라우팅되는 것을 발견했다. ip_input.c 는 제대로 작동하고 있는것 같았지만 ip_output.c 는 그렇지 않았다. 출력 프로그램의 소스 코드를 읽는 동안 외부로 나가는 데이터그램들이 라우팅 여부를 결정하는 함수 ipmr_forward()를 거치지 않는 것을 발견했다. 패킷들은 로컬 네트웍으로 출력되었지만 네트웍 카드는 자신이 전송하는 데이터그램을 읽을 수 없었고, 이런 데이터그램들은 라우팅되지 않았다. 우리가 ip_build_xmit() 함수에 적절한 코드를 추가하자 모든 것이 올바로 작동하였다. (소스 수정은 사치를 떠는 것도 유식한척하는 것도 아니다; 필요다!)
ipmr_forward() 는 수 차례 언급했었다. ipmr_forward() 는 우리가 흔히 잘못 이해하고 있는 것을 풀어줄 수 있기 때문에 아주 중요한 함수이다. 멀티캐스트 트래픽을 라우팅할 때, 패킷 사본을 만들고 그것을 올바른 수신자에게 전달하는 것은 mrouted자체가 아니다. mrouted는 모든 멀티캐스트 트래픽을 수신하여, 그 정보에 근거하여 , 멀티캐스트 라우팅 테이블을 계산해 내고 커널에 라우팅 방법을 알려준다. "이 인터페이스에서 들어오는 저 그룹의 데이터그램은 저 인터페이스로 보내라."
이 라우팅 정보는 mrouted 데몬(raw 소켓 생성시 지어된 프로토콜은 IPPROTO_IGMP이어야 한다.)이 만든 raw 소켓에서 setsockopt()를 호출하여 커널에 설정한다. 이 옵션은 LINUX/net/ipv4/ipmr.c 의 ip_mroute_setsockopt()함수에서 처리한다. 소켓에서 발행한 첫번째 옵션(would be better to call them commands rather than options)은 MRT_INIT이어야 한다. 첫 번째 발행한 옵션이 MRT_INIT이 아니라면 다른 모든 명령은 무시한다. (-EACCES를 반납) 한 호스트 상에는 mrouted의 인스턴스가 꼭 하나만 존재할 수 있다. 이것을 추적하기 위해 첫 번째 MRT_INIT 을 받았을 때 구조체 sock* mroute_socket이 MRT_INIT 을 수신한 소켓을 가리키게 된다. 만일 MRT_INIT 을 발행했을때 mroute_socket이 널(null)값을 가지지 않는다면 이미 다른 mrouted가 작동중임을 의미하므로 -EADDRINUSE 을 반납한다. 나머지 다른 명령들(MRT_DONE, MRT_ADD_VIF, MRT_DEL_VIF, MRT_ADD_MFC, MRT_DEL_MFC and MRT_ASSERT)은 mroute_socket과 다른 소켓에서 올 경우 -EACCES 를 반납한다.
라우팅된 멀티캐스트 데이터그램은 물리적 인터페이스 혹은 (가상적인) 터널을 통해 전송하기 때문에, 일반적인 추상화(abstraction) 단계를 VIFs, 즉, 가상 인터페이스 (Virtual InterFaces)고안해냈다. mrouted는 물리 혹은 터널 인터페이스를 가리키는 vif 구조체를 라우팅 테이블에 추가하기 위하여 커널에 넘겨주고, 데이터그램을 어디로 포워딩할지 알려주는 멀티캐스트 포워딩 목록(multicast forwarding entries)에도 알려준다.
VIFs 는 MRT_ADD_VIF 로 추가하고 MRT_DEL_VIF 로 삭제한다.두 함수 모두 vifctl 구조체를 커널로 넘긴다. ( /usr/include/linux/mroute.h) 에서 다음과 같이 정의하고 있다.
struct vif_device
{
struct device *dev; /* Device we are using */
struct route *rt_cache; /* Tunnel route cache */
unsigned long bytes_in,bytes_out;
unsigned long pkt_in,pkt_out; /* Statistics */
unsigned long rate_limit; /* Traffic shaping (NI) */
unsigned char threshold; /* TTL threshold */
unsigned short flags; /* Control flags */
unsigned long local,remote; /* Addresses(remote for tunnels)*/
};
이 구조체에서 dev 항목을 주목하라. device 구조체는 /usr/include/linux/netdevice.h 에서 정의하고 있다. 아주 큰 구조체이지만 우리는 다음 필드에만 관심을 두면 된다.
struct ip_mc_list* ip_mc_list; /* IP multicast filter chain */
ip_mc_list 구조체는 /usr/include/linux/igmp.h에서 다음과 같이 정의하고 있다. :
struct ip_mc_list
{
struct device *interface;
unsigned long multiaddr;
struct ip_mc_list *next;
struct timer_list timer;
short tm_running;
short reporter;
int users;
};
dev 구조체의 ip_mc_list 는 ip_mc_list 형 구조체의 연결리스트를 가리키는 포인터이다. ip_mc_list 는 해당 네트웍 인터페이스가 멤버로 참여하고 있는 멀티캐스트 그룹을 담고있다. 여기서 다시 한번, 회원은 인터페이스와 관계가 있음을 알 수 있다. LINUX/net/ipv4/ip_input.c 는 데이터그램이 (데이터그램을 수신한 인터페이스가 속하는 그룹 가운데) 어떤 그룹에 속한 것인지 결정하기 위해 이 연결리스트를 순회한다.
#ifdef CONFIG_IP_MULTICAST
if(!(dev->flags&IFF_ALLMULTI) && brd==IS_MULTICAfST
&& iph->daddr!=IGMP_ALL_HOSTS
&& !(dev->flags&IFF_LOOPBACK))
{
/*
* Check it is for one of our groups
*/
struct ip_mc_list *ip_mc=dev->ip_mc_list;
do
{
if(ip_mc==NULL)
{
kfree_skb(skb, FREE_WRITE);
return 0;
}
if(ip_mc->multiaddr==iph->daddr)
break;
ip_mc=ip_mc->next;
}
while(1);
}
#endif
ip_mc_list구조체에서 users 필드는 "IGMP 버전 1"에서 설명했던 것을 구현하기 위해 사용한다. 프로세스가 그룹에 참여 할때, 인터페이스가 이미 그 그룹의 회원이라면 (다시 말해서, 동일 인터페이스로 동일 그룹에 참여한 프로세스가 이미 있으면) 멤버 수(users)만 증가시킨다. IGMP 메시지를 보내지 않음을, 다음 코드에서 볼 수 있다. (ip_mc_inc_group() 에서 가져왔으며, ip_mc_join_group() 와 LINUX/net/ipv4/igmp.c에서 호출한다.)
멤버가 탈퇴할 때 카운터를 감소하며, 카운터가 0에 다다랐을 때에만 부가적인 작업을 수행한다. (ip_mc_dec_group()).
MRT_ADD_MFC 와 MRT_DEL_MFC 는 멀티캐스트 라우팅 테이블에서 포워딩 항목을 성정하거나 삭제한다. 둘 다 mfcctl 구조체를 다음 정보와 함께 커널로 넘긴다. (/usr/include/linux/mroute.h 에서 정의)
struct mfcctl
{
struct in_addr mfcc_origin; /* Origin of mcast */
struct in_addr mfcc_mcastgrp; /* Group in question */
vifi_t mfcc_parent; /* Where it arrived */
unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */
};
이상의 정보를 가지고, ipmr_forward() 는 VIFs를 "돌아다닌다". 그리고 일치하는 포워딩 항목을 발견하면 데이터그램을 복사하여 ipmr_queue_xmit()을 호출한다. 그러면, ipmr_queue_xmit() 은 패킷을 터널을 통해 보낼 경우 라우팅 테이블에 명시 돤 출력장치와 목적지 주소를 이용해 전송한다. (즉, 반대편 터널 종단의 유니캐스트 주소) 함수 ip_rt_event() 는(출력과 직접적인 관련은 없지만 ip_output.c 에 들어 있다.) 장치 활성화 메시지 같은 네트웍 장치 관련된 이벤트(event)를 받는다. 이 함수는 장치가 전체 호스트 그룹에 참여하는 것을 보증한다.
IGMP 함수들은 LINUX/net/ipv4/igmp.c 에서 구현한다. 이 함수들에 관한 중요한 정보는 /usr/include/linux/igmp.h 와 /usr/include/linux/mroute.h 에 있다. /proc/net 의 IGMP 관련 항목은 LINUX/net/ipv4/ip_output.c에 있는 ip_init() 에서 만든다.
별로 좋지 않은 알고리즘은 멀티캐스트 데이터 수신 의사와 상관없이 전 세계로 트래픽을 내보낸다. 이런 최적화 되지 않은 알고리즘을 대신할 몇 가지 포워딩 기술과 라우팅 알고리즘이 개발되었다.
거리 벡터 멀티캐스트 라우팅 프로토콜 DVMRP (Distance Vector Multicast Routing Protocol) 는 아마도 오늘날 멀티캐스트 라우터 대부분이 사용하고 있는 알고리즘일 것이다. 이것은 고밀도형(dense mode) 라우팅 프로토콜, 즉, 높은 대역폭에 멤버들이 고밀도로 분산되어있는 있는 환경에서 잘 작동한다. 하지만, 멤버들이 낮은 밀도로 흩어져있는 경우 문제(scalability problem)가 있다.
DVMRP 같은 고밀도형 라우팅 프로토콜로 멀티캐스트 확장형 최단거리 우선 프로토콜 MOSPF (Multicast Extensions to OSPF -Open Shortest Path First-) , 프로토콜 독립형 고집적 멀티캐스트 PIM-DM (Protocol-Independent Multicast Dense Mode) 그리고 중심 기반 트리 CBT (Core Based Trees) 가 있다.
OSPF 버전 2 는 RFC 1583 , MOSPF 는 RFC 1584 , PIM-SM 과 CBT 는 각각 RFC 2117 과 2201 이 규격을 명시하고 있다.
이 모든 라우팅 프로토콜들은 flooding, Reverse Path Broadcasting (RPB), Truncated Reverse Path Broadcasting (TRPB), Reverse Path Multicasting (RPM) or Shared Trees 같은 멀티캐스트 포워딩 기술을 사용한다.
내용이 너무 길어지므로 이 모든 것들을 여기서 설명하지는 않겠다. 이것들에 대한 해설은 쉽게 찾아볼 수 있을 것이다. draft-ietf-mboned-in.txt 문서를 읽어 볼 것을 권한다. 위의 RFC 들이 있는 곳에 같이 있을 것이며, 상기한 기술과 정책들에 대한 약간 자세한 내용을 담고있다.
지금까지 UDP를 이용한 멀티캐스트 전송에 대해 알아보았다. TCP에서는 불가능하기 때문에 이상이 일반적인 내용이다. 그렇지만, 좀더 새로운 멀티캐스트 트랜스포트 프로토콜 (Multicast Transport Protocols) 을 만들어내기 위해 지난 몇 년간 집중적인 연구가 계속되고 있다.
새로 개발된 프로토콜 가운데 몇 가지는 구현 단계를 거쳐 테스트 단계까지 이르고 있다. 모든 형태의 응용에 적합한 일반적인 멀티캐스트 트랜스포트 프로토콜은 존재하지 않는다는 것이, 연구를 통해 밝혀지는 것 같다.
아주 복잡하고 조정하기 어려운 프로토콜에서 다음과 같은 문제들을 생각해 보자. 지연(멀티미디어 회의에서), 자료 손실, 패킷 정렬(ordering), 재전송, 흐름 및 혼잡도 조정, 그룹 관리 등.....게다가 수신자가 하나가 아니라 수백 수천 개의 저밀도 분산 호스트들이라면...이런 경우에 조정에 큰 곤란을 겪을 것이다. 따라서, 수신한 모든 패킷에 대해 수신 확인(ACKs)을 보내는 대신, 수신하지 못한 패킷에 대해서만 수신 불량 신호(NACKs)를 보내는 식의 알고리즘을 개발한다. RFC 1458 이 멀티캐스트 프로토콜 요구사항을 제안하고 있다.
멀티캐스트 프로토콜에 대한 자세한 해설은 문서의 범위를 넘기 때문에 더 이상 설명하지 않을 것이지만, 대신, 프로토콜 이름과 자료를 찾아 볼 수 있는 요점만 짚고 넘어가도록 하겠다. Real-Time Transport Protocol (RTP) 은 분산형 멀티미디어 회의(multi-partite multimedia conferences)와 관련 있으며, Scalable Reliable Multicast (SRM) 은 wb (the distributed White-Board tool, see section ``Multicast applications'')가 사용한다. Uniform Reliable Group Communication Protocol (URGC) 은 중앙 집중식 제어에서 자료 처리(transaction) 가 신뢰적이며 정연히 이루어질 수 있도록 도와준다. Muse 는 MBone 에서 뉴스를 전송할 수 있도록 특정 프로그램용으로 고안된 것이며, Multicast File Transfer Protocol (MFTP) 은 문자 그대로 파일 전송과정 회의에 참여하듯이 참여 할수 있도록 해주는 프로토콜이다. Log-Based Receiver-reliable Multicast (LBRM) 은 기록 서버(logging server) 로 보내지는 모든 패킷을 추적하여 전송측에 데이터를 다시 전송해야하는지 아니면 이상 없이 수신되었는지 알려주는 특이한 프로토콜이다. 또 한가지, 멀티캐스트 프로토콜이면서 STORM (STructure-Oriented Resilient Multicast)이라는 재미있는 이름을 가진 프로토콜도 있다. 웹을 찾아보면 이 외에다 많은 멀티캐스트 프로토콜이 있으며 멀티캐스트를 이용해 새로운 일들을 벌이려는 재미있는 내용의 글들도 많다.(예를 들어, 멀티캐스트를 이용한 웹 페이지 자동 전송 같은 것)
Katia Obraczka의 "Multicast Transport Protocols: A Survey and Taxonomy" 라는 글은 각 프로토콜에 대한 간단한 설명을 하고 기능상 차이점으로 분류하고 있다. 이 글은 IEEE Communications magazine, January 1998, vol. 36, No. 1. 에도 실려있다.
RFC 1112 "Host Extensions for IP Multicasting". Steve Deering. August 1989.
RFC 2236 "Internet Group Management Protocol, version 2". W.Fenner. November 1997.
RFC 1458 "Requirements for Multicast Protocols". Braudes, R and Zabele, S. May 1993.
RFC 1469 "IP Multicast over Token-Ring Local Area Networks". T. Pusateri. June 1993.
RFC 1390 "Transmission of IP and ARP over FDDI Networks". D. Katz. January 1993.
RFC 1583 "OSPF Version 2". John Moy. March 1994.
RFC 1584 "Multicast Extensions to OSPF". John Moy. March 1994.
RFC 1585 "MOSPF: Analysis and Experience". John Moy. March 1994.
RFC 1812 "Requirements for IP version 4 Routers". Fred Baker, Editor. June 1995
RFC 2117 "Protocol Independent Multicast-Sparse Mode (PIM-SM): Protocol Specification". D. Estrin, D. Farinacci, A. Helmy, D. Thaler; S. Deering, M. Handley, V. Jacobson, C. Liu, P. Sharma, and L. Wei. July 1997.
RFC 2189 "Core Based Trees (CBT version 2) Multicast Routing". A. Ballardie. September 1997. RFC 2201 "Core Based Trees (CBT) Multicast Routing Architecture". A. Ballardie. September 1997.
10.2 인터넷 초안(draft)
"Introduction to IP Multicast Routing". draft-ietf-mboned-intro- multicast- 03.txt. T. Maufer, C. Semeria. July 1997.
"Administratively Scoped IP Multicast". draft-ietf-mboned-admin-ip-space-03.txt. D. Meyer. June 10, 1997.
"TCP/IP Illustrated: Volume 1 The Protocols". Stevens, W. Richard. Addison Wesley Publishing Company, Reading MA, 1994
"TCP/IP Illustrated: Volume 2, The Implementation". Wright, Gary and W. Richard Stevens. Addison Wesley Publishing Company, Reading MA, 1995
"UNIX Network Programming Volume 1. Networking APIs: Sockets and XTI". Stevens, W. Richard. Second Edition, Prentice Hall, Inc. 1998.
"Internetworking with TCP/IP Volume 1 Principles, Protocols, and Architecture". Comer, Douglas E. Second Edition, Prentice Hall, Inc. Englewood Cliffs, New Jersey, 1991
이 하우투 문서는 Free Software Foundation에서 선언한 GNU General Public License 버전 2 또는, 최신 버전의 License에 따라 자유롭게 재 배포할 수 있으며 수정할 수 있다.
이 문서가 여러문에게 도움이 되기를 원하는 의도에서 배포 하였지만. 어떠한 보증도 하지 않는다.자세한 사항은 GNU General Public License를 참고 하라.
GNU General Public License는 아래 주소로 편지를 보내면 얻을 수 있다.
The Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
이 문서를 CD-ROM이나 다른 매체에 수록하여 배포할 경우 저자에게 사본을 보내주면 고맙겠다. GNU/Linux 문서화를 위해 Linux Documentation Project 나 Free Software Foundation에 여러분의 도움을 주기바란다. 자세한 내용은 Linux HOWTO 관리자, Tim Bynum linux-howto@sunsite.unc.edu에게 문의하면 된다.
이곳은 내가 감사드릴 사람을 밝힐 좋은 기회인것 같다. 이 장의 내용이 다소 커질것 같다..... 어쨌든 이곳은-적어도 내게있어서-이 문서에서 가장 중요한 부분이다.
우선, Elena Apolinario Fernandez de Sousa (Elena가 이름,나머지가 성이다 ;-) )에게 감사드리고 싶다. 우리 부서를 MBone과 연결하는 과정, 그리고 우리가 멀티캐스트 터널용으로 제작한 CSCV 소프트웨어를 디버깅하는 과정에서 그녀와 함께 일하며 얻은 모든 지식을 이 문서에 반영하려고 노력하였다. 그녀는 네트웍 문제를 찾아내 해결하고 커널의 버그를 수정하는데 많은 도움을 주었으며, 계속되는 버그와의 싸움에서도 유머감각을 잃지 않았다. 또, 그녀는 이문서의 초안을 읽고 수정해 주었으며 중요한 제안을 해 주었다. 이 문서가 사람들에게 도움이 되었다면 상당부분 그녀 덕분일 것이다. 고마워, Elena!
얼마 길지 않은 인생이지만 내 생애에서 정말 운 좋다고 생각하는 것은, 자기 시간을 쪼개서 이런 새로운 것을 배우는 남을 돕고 그 자체를 좋아하는 사람들을 만났다는 것이다. 그분들은 자신이 이미 아는 것을 설명해주었으며 그 뿐만 아니라 책을 빌려주고 자료와 설비를 공유해 주었다. 나는 이런 분들을 많이 알고 있으며 그분들에게 감사의 뜻을 전하고자 한다.
Pablo Basterrechea는 내가 인터넷 초보자일때 많은 문서들을 빌려주었다. 그의 책으로 어셈블리를 공부하고 구조적 프로그래밍으로 나아 갈 수 있었다. 고맙네, Pablo.
내가 대학 신입생때 Pepe Mas씨가 많은 도움을 주었다. 그는 컴퓨터 프로그래밍을 가르치는 문이었는데, 나는 곧 그분의 서가에 홀려버렸다. 내가 책을 제때에 제대로 돌려줄 것이라는 보증이 없었는데도 이름조차 물어보지 않고 조건없이 책을 빌려주었다. 그 분의 책 즉, Comer의 "Internetworking with TCP/IP, Volume 1"을 여름 내내 보며 처음으로 TCP/IP를 접했다. 이 책은 내게 많은 영향을 미쳤으며 그 여름 이후로 TCP/IP는 주 분야가 되었다.
내가 가장 감사드려야 할 분이 있다면, 알파벳 순서로 ;-), Jos Manuel 과 Paco Moya 이 두명이다. 이 두 명에게 나는 궁금한 것을 가장 많이 물었다.(C, C++, Linux, security, Web, OSs, signals & systems, electronics, ... 그외의 것들 모두!) 나의 계속되는 질문에도 불구하고 언제나 친절하게 알려주었다.내가 GNU/Linux를 쓰는 것도 그들 덕이며 정말로 감사드리는 분들이다.
Igo Mascaraque 역시 초보 시절 나를 도와 주고 포기하지 않도록 용기를 북돋아 주었다.
제일 중요한 부모님께 감사드리고 싶다. 언제나 내게 좋은 기회를 주셨다. 정말로 감사드린다.
내가 처음 시스템 관리를 독학 할때 root 패스워드를 내게 줄 정도로 나를 믿어준 Joaqu Seoane에게도 감사드린다. 또, 역시 이곳 DIT에서 내게 좋은 기회를 만들어준 Santiago Pav에게도 감사드린다.
W. Richard Stevens씨의 책은 내게 정말 계시와도 같은 책이었다.(비싼게 흠이긴 하지만) 그 분이 혹시라도 이 글을 보신다면 정말로 감사드리고 싶다. 또, 계속 집필해 주시기를 부탁드린다. 우리에게 많은 도움이 될 것이다.
끝으로 Richard Stallman, Linus Torvalds, Alan Cox, 그 외에, 우리에게 이런 훌륭한 운영체제를 안겨준 Linux 커널 및 free software 개발자들에게 감사드린다.
누군가 잊은것 같긴 하지만 ..죄송...내가 그 분들에게 감사해하고 있다는 것을 알고 계시리라 확신한다.
This article details the configuration of Broadcom 43xx series devices by three differnt methods. Note that this article only covers the specifics required for these devices. For generic installation instructions please see the Gentoo Handbook.
Enable the following options in the kernel, then build and install as normal. The deselected options are possible extras or alternatives, depending on your device.
Linux Kernel Configuration: b43 / b43-legacy kernel options (2.6.25+)
Bus options (PCI etc.) -->
< > PCCard (PCMCIA/CardBus) support --->
[*] Networking support -->
Wireless -->
-*- Improved wireless configuration API
-*- Wireless extensions
<*> Generic IEEE 802.11 Networking Stack (mac80211)
Device Drivers -->
Network device support -->
Wireless LAN
[*] Wireless LAN (IEEE 802.11)
<*> Broadcom 43xx wireless support (mac80211 stack)
[ ] Broadcom 43xx PCMCIA device support
[*] Broadcom 43xx debugging
< > Broadcom 43xx-legacy wireless support (mac80211 stack)
[ ] Broadcom 43xx-legacy debugging
Broadcom 43xx-legacy data transfer mode (DMA + PIO) --->*
(*) Broadcom 43xx-legacy data transfer mode (DMA + PIO) kernel option reports that "not all devices of the b43legacy series support PIO. You should use PIO only if DMA does not work for you."
The following options may enable support for laptop LEDs.
Linux Kernel Configuration: Extra Options for Laptops (2.6.25+)
[*] Networking support --->
Wireless --->
<*> Generic IEEE 802.11 Networking Stack (mac80211)
[*] Enable LED triggers
<*> RF switch subsystem support --->
<*> Input layer to RF switch connector
Device Drivers --->
[*] LED Support --->
[*] LED Trigger support
<*> LED Timer Trigger
<*> LED Heartbeat Trigger
<*> LED Default ON Trigger
Input device support --->
-*- Generic input layer (needed for keyboard, mouse, ...)
<*> Polled input device skeleton
Firmware / fwcutter
In addition to the kernel driver, you will need the firmware and a firmware cutter (which extracts the firmware and places it in /lib/firmware) for your card.
For a list of supported devices and the latest information for each driver, see the relevent project documentation page:
Now extract the firmware file (replacing the example used below with the version of firmware recommended by the b43 documentation):
tar -xjf broadcom-wl-4.150.10.5.tar.bz2
then
cd broadcom-wl-4.150.10.5/driver
If /lib/firmware does not exist, create it:
mkdir /lib/firmware
Cut the firmware with:
b43-fwcutter -w /lib/firmware <firmware file>
If you opted to compile the driver as a module, it will be named either b43 or b43legacy.
For most users, installation should now be complete. Reboot and configure your wireless.
Monitor mode
To set your card into monitor mode, you also need to patch the b43 and mac80211 module. The monitor mode is only needed for packet injection to be used for aircrack-ng and similar tools.
The latest version that works with this card is, aircrack-ng 1.0 RC1. You can obtain an ebuild from Bug #233285.
Kernel 2.6.25
cd /usr/src/linux/
wget http://patches.aircrack-ng.org/b43-injection-2.6.25-wl.patch
wget http://www.latinsud.com/bcm/mac80211_2.6.24.4_frag.patch
patch -p1 < b43-injection-2.6.25-wl.patch
patch -p1 < mac80211_2.6.24.4_frag.patch
make && make modules_install
Kernel 2.6.26
It is best to use the wireless testing kernel to patch against:
cd /usr/src
git clone git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
cd /usr/src/linux/
wget http://patches.aircrack-ng.org/b43-injection-2.6.26-wl.patch
wget http://patches.aircrack-ng.org/mac80211_2.6.26-wl_frag.patch
patch -p1 < b43-injection-2.6.26-wl.patch
patch -p1 < mac80211_2.6.26-wl_frag.patch
make && make modules_install
Ndiswrapper
If the process above doesn't work, you can try to use the ndiswrapper drivers are the drivers that came with your laptop or wireless card. If those fail, check for the latest version from the manufacturers website.
Note: Vista drivers are not supported because ndiswrapper does not support version 6 of the NDIS API yet
Note: Make sure to grab the 64 bit version of the driver if you are running x86_64. This can be a problem because not all chipsets necessarily have 64 bit XP drivers
If you own a macbook (4th or 5th generation) try using the bootcamp winxp driver. It's located on the 1st install DVD and named "broadcomxpinstaller.exe", just unrar it.
Broadcom has released it's own kernel driver. It's closed source but works and seems to release "often" (at least 3 times between the summer of 2008 and the February 2009).
There is now a masked ebuild (net-wireless/broadcom-sta) so one no longer has to compile it by hand. The ebuild also contains patches so that it will work on the latest kernel. Just unmask the package and emerge as usual.
Note: It might be necessary to run "update-modules -f" to install the driver correctly! This was required before it was an ebuild, but if you are having issues loading the module.
Troubleshooting
General Advice
Your first port of call when problems arise is the output of dmesg, which displays the kernel log. It is also helpful to make sure that only one of the 3 possible modules is loading. The best way to due this is blacklist the modules you don't want. Add the relevant entries from below.
File: /etc/modules.d/blacklist
blacklist ndiswrapper
blacklist b43
blacklist wl
WEP encryption is not enabled for your device
If you get an error message saying "WEP encryption is not enabled for your device" or similar it may be necessary to compile the following into the kernel to ensure that the required cryptographic options are enabled. If you compile the cryptographic options as modules, they may not be loaded automatically by the driver.
iwconfig reports txpower off
On some laptops the driver does not initialise the device in powered on mode. This can be resolved by adding the following to your network configuration (assuming wlan0 is the device name).
File: /etc/conf.d/net
postup () {
if [[ ${IFACE} == "wlan0" ]]; then
iwconfig wlan0 txpower on
fi
}