2009년 7월 13일 월요일

서버내에서 간단한 트래픽제어

Traffic Control for LRP



작성 : 신중갑(ifw00@dreamwiz.com) 2002년 6월 22일

참고 : 이 문서에서 설명하는 속도제어는 간단한 홈네트워크를 위한 것이며 기본적인 옵션만을 사용해 LRP를 이용한 인터넷생활에서 필요한 간단한 속도제어만을 구현할 것이다. 그렇다고 기능이 제한되어 있는 것은 아니므로 좀 더 연구하면 복잡한 것도 구현가능하다.


차례
1. 소개
2. 파일다운로드
2.1 cbq.init 사용시 필요한 파일들
2.2 htb.init 사용시 필요한 파일들
3. 알아두어야할 기본사항
3.1 packet mark
3.2 LRP에서 사용시
4. cbq.init를 이용한 속도제어
5. htb.init를 이용한 속도제어


1. 소 개

LRP를 이용해서 IP를 공유해 여러명이 사용하다보면 한 사람이 ftp 다운로드나 업로드 등을 통해 대부분의 대역폭을 사용해 다른 사람에게 불편을 주는 경우가 있다. 웹서핑이나 telnet 등은 일반적으로 대역폭에 거의 영향이 없으므로 TOS값 조절 등을 통해 트래픽의 우선순위를 높이는게 오히려 더 나을 것이다.

여기서는 리눅스에서 사용되는 대표적인 방법인 CBQ(Class Based Queueing)와 HTB(Hierachical Token Bucket) 두 가지를 다루기로 한다. HTB는 CBQ보다 좀더 진보한 방식으로 평가받고 있다. 다만 아직 공식적으로 커널에 채용되지 않았기에 커널컴파일시 패치를 해줘야 하는 불편이 있다. HTB는 Martin Devera가 제작한 것으로 현재 HTB3 public beta까지 나와있으며 kernel 2.4전용이기 때문에 kernel 2.2.x 를 사용한다면 HTB2를 사용해야 한다. 아직까지 LRP에서는 커널 2.2 가 주로 쓰이므로 여기서는 HTB2를 사용하기로 한다.

사용한 LRP배포판은 Dachstein v1.0.2 플로피버전을 수정한 것으로 다른 배포판에서는 실험해보지 않았다. CBQ, HTB 둘다 원래 사용방법은 다음과 같이

tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps

커맨드프롬프트상에서 tc를 이용하여 직접 입력하는 방식이다. 하지만 세밀한 조절은 가능할 지 몰라도 많은 명령과 문법을 알아야 하기에 불편하므로 간편하게 사용하고자 스크립트가 나왔다. 2002년 6월 5일 현재 CBQ의 경우 cbq_init-v0.7(written by Paul Golubev), HTB는 htb_init-v0.8.3(written by Lubomir Bulej) 까지 나와있다. 둘다 내용과 사용법이 비슷한데 이는 htb.init 스크립트가 cbq.init 를 HTB에 맞게 고쳐서 나온 것이기 때문이다. 이 스크립트들을 이용하면 간단한 설정파일을 만드는 것만으로 속도제어가 가능하다.


2. 파일다운로드

먼저 tcfiles.lrp 를 받도록 한다. cbq.init, htb.init 공통적으로 필요한 파일들을 모은 패키지로서 내용물은 다음과 같다.

find : 4.1-25
grep : 2.2
tee : 1.16
sed : 3.02
ip : iproute2-ss010824
tc : iproute2-ss010824

HTB의 경우 tc 패치를 해줘야 하는데 tcfiles.lrp에 들어있는 tc는 이미 패치가 되어있고 또한 cbq에서도 사용할 수 있다. find, grep 등이 lrp에서 사용가능함에도 따로 넣은 이유는 리눅스와 달리 lrp에서는 이러한 명령을 용량상 보통 busybox로 대체하는데 스크립트에서 사용되는 몇몇 옵션이 빠져있기 때문이다. htb.init에서는 busybox를 사용할 수 있는 옵션이 있지만 실행시 느리므로 디스켓용량이 모자르지 않다면 그대로 쓰는게 낫다.

2.1 cbq.init 사용시 필요한 파일들

파일명
용  량
비  고
cbqinit.lrp 32KB cbq.init-v0.7, 모듈
커널*   qos and/or fair queueing 지원되어야 함.

  • cbqinit.lrp 에는 필요한 모듈과 cbq.init-v0.7 스크립트가 들어있다. lrp의 환경에 맞게 약간 수정했다.
  • 커널 : 자신이 사용중인 lrp 커널이 qos and/or fair queueing 이 활성화되어있는지 알아야 한다. Dachstein v1.0.2 커널 2.2.19의 경우 크게 small, normal, RAID 3가지로 나뉘고 각각은 IPSEC, IDE 등의 조합으로 컴파일되어 여러가지 종류의 커널이 홈페이지에 올라와 있다. 플로피버전의 경우 small버전을 사용하는데 qos and/or fair queueing부분이 비활성화되어있으므로 Dachstein 플로피버전을 사용한다면 normal버전이상으로 바꾸어야 한다. 특별히 IPSEC 등을 사용하지않는다면 linux-2.2.19-3-LEAF-normal.zImage.upx 를 받으면되며 파일명을 linux로 바꿔 lrp디스켓에 복사한다.

    2.2 htb.init 사용시 필요한 파일들

    파일명
    용  량
    비  고
    linux-2.2.19htb 453KB 커널 2.2.19 HTB2 패치 ('다른 이름으로 대상저장'할 것)
    bash.lrp 314KB Dachstein용 bash. libncurses.so.4, libreadline.so.2 포함
    htbinit.lrp 27KB htb.init-v0.8.3, 모듈

  • HTB의 경우 커널에 패치를 해주고 컴파일해줘야하는데 기존에 만들어진 것이 없어서 직접 컴파일했다. Dachstein v1.0.2 normal-IPSec.config 설정을 기본으로 했고 freeswan ipsec v1.91 대신 1.97 패치를 해줬으며 모듈화했다. cbq.init 스크립트사용시에도 사용할 수 있다.
  • htb.init의 경우 cbq와 달리 sh에서는 에러가 나므로 bash에서 실행해야 한다. 따라서 bash 패키지가 필요한데 Dachstein에서 기존의 bash 패키지를 사용했을때의 문제점을 해결한 bash 패키지 에 필요한 라이브러리를 같이 넣었다.
  • htbinit.lrp 에는 필요한 모듈과 htb.init-v.0.8.3 스크립트가 들어있다. 역시 lrp 환경에 맞게 약간 수정했다.

    3. 알아두어야할 기본사항들

    3.1 packet mark

    lrp박스에 eth0, eth1 두 nic가 있다고 하자. eth0은 외부, eth1은 내부로 연결된다.

                                      +----------+                      192.168.1.1
    internet -------- eth0 -|   lrp box   |- eth1 -------- [client]
                                      +----------+

    주의! 속도제어는 인터페이스에서 나가는 트래픽만이 가능하다
    . 즉, 다운스트림을 제한하고 싶으면 eth1을 기준으로 설정을 한다. 업스트림은 eth0을 기준으로 한다. 이는 자신의 환경에 맞춰 바꾼다. 자세한 것은 아래 cbq, htb 각각의 설정파일을 보면 알 수 있으며 cbq, htb 둘다 공통사항이다. 인터페이스이름을 잘못 지정하면 안되므로 주의하도록 한다.

    eth0과 eth1 전체의 트래픽을 설정하는 것은 크게 문제가 안된다. 클래스를 만들고 각각에 필요한 만큼의 속도제한을 가해주면 된다. 하지만 ip, port, 업다운 스트림 별로 자신의 구미에 맞게 자세히 설정하려면 패킷필터링을 거쳐야 하는데 이는 패킷에 mark를 해주고 이를 이용해 cbq나 htb가 지나가는 트래픽중 그것만을 골라서 제어하는 것이다. mark는 ipchains나 iptables로 한다.

    다운스트림의 경우 특별히 해 줄 것이 없다. mark없이 cbq, htb 스크립트의 설정만으로 쉽게 속도제어가 가능하다.

    업스트림의 경우는 mark를 해줘야 한다. 이유는 마스커레이딩때문인데 다운스트림과 달리 내부 네트워크의 사설주소가 공식IP로 번역되면서 어떤 패킷에 속도제한을 가해야 할지 모르기 때문이다. 특정패킷에 mark 를 해줌으로써 외부로 나가는 패킷 중 그 패킷만을 골라내 업스트림 속도제어를 할 수 있다.

    ipchains로 업스트림의 패킷에 마크를 할 경우 다음과 같이 한다.

    ipchains -I input -p tcp -s xxx.xxx.xxx.xxx/mask sport -d yyy.yyy.yyy.yyy/mask dport -m marknumber
  • ipchains 뒤 -I는 i의 대문자이다. L의 소문자 l이 아니다.
  • -s 는 source 의 뜻이다. 즉 -s 뒤에 패킷이 시작하는 ip나 포트를 지정한다. 여기서는 업로드의 경우에 한해서이므로, xxx.xxx.xxx.xxx는 내부 네트워크 클라이언트의 주소, 즉 192.168.1.10 같은 lrp뒤 내부네트워크의 사설IP이다.
  • /mask 는 서브넷 마스크이다. 0은 모두를, 32는 특정 ip 하나만을 지칭한다.
  • sport는 소스어드레스의 포트이다.
  • -d 는 destination, 즉 목적지를 나타낸다.
  • yyy.yyy.yyy.yyy는 목적지주소이다. 특정 ip를 지정할 수도 있고 모든 인터넷 주소를 포함시키려면 0/0 이라고 하면 된다.
  • dport 는 목적지의 특정 포트를 가리킨다.
  • marknumber는 숫자로서 십진수로 한다. 0x01 같이 16진수로 할 수도 있다.

    예를 들면:
    ex3.1)

    ipchains -I input -p tcp -s 192.168.1.10 -d 0/0 20:21 -m 11

    내부 클라이언트 192.168.1.10에서 인터넷상의 외부ftp서버(포트 20,21)로 업로드하는 패킷에 11로 mark한다.

    ex3.2)

    ipchains -I input -p tcp -s 192.168.1.10 9292 -d 0/0 -m 12

    내부클라이언트 192.168.1.10에서 구루구루(포트 9292)에서 업로드하는 패킷에 12로 mark한다.

    3.2 LRP에서 사용시

    cbqinit.lrp, htbinit.lrp 둘다 자동으로 실행되지 않게 돼있다. 따라서 부팅시 시작되는 시스템스크립트에 시작명령을 포함시키도록 한다. 잘 모르겠으면 포트포워딩시 수정하는 스크립트를 이용하도록 한다. 업스트림제어시 필요한 ipchains 구문도 마찬가지로 같이 넣는데 단 속도제어스크립트보다 먼저 실행되게 순서를 위로 올리는게 좋다.

    lrcfg - 패키지 메뉴에서 각 스크립트의 이름은 보이나 막상 설정파일에서는 아무것도 안나온다. 이는 각각의 스크립트를 필요한만큼 따로 만들어야 하기 때문이다. cbq.init와 htb.init 각각의 설정파일위치는 /etc/sysconfig 내에 있다. 필요한 설정파일을 만들면 반드시 백업을 하도록 한다.


    4. cbq.init 를 이용한 속도제어

    먼저 cbq.init 앞의 주석문을 읽어보도록 한다. 많은 옵션과 설명이 있으므로 꼭 읽어보도록 한다. 시간대별로 속도를 설정할 수 있고 크게 지역을 설정해 지역별로 속도제어를 할 수도 있다. 하지만 여기서는 문서초기에 언급했듯이 간단한 속도제어만을 구현해본다.

    cbq.init 스크립트는 /usr/sbin 에 있으며 패스가 걸려있어 어디에서든 실행가능하다. 설정파일은 /etc/sysconfig/cbq 에 놓아야 하는데 디렉토리위치는 스크립트내 CBQ_PATH 부분을 수정해서 바꿀 수 있다.

    i### Default CBQ_PATH & CBQ_CACHE settings
    CBQ_PATH=${CBQ_PATH:-/etc/sysconfig/cbq}
    CBQ_CACHE=${CBQ_CACHE:-/var/cache/cbq.init}        

    설정파일명의 형식은

    cbq-<classid>.name

    와 같다. class id는 16진수로 2 부터 FFFF 까지이다. name은 말그대로 설정파일에 대한 간단한 설명을 나타낸 이름이다. 한 파일에 한 트래픽에 대한 속도를 설정할 수 있다. 즉, ftp, 구루구루 두 프로그램에 대한 속도를 제한하고 싶으면 설정파일은 다음과 같이

    cbq-020.ftpdown
    cbq-030.guruguruup

    두 개의 파일을 만들면 된다. 예를 들어 설명해보면:

    ex4.1) ftp 다운로드 속도제한

    #cbq-020.ftpdown

    DEVICE=eth1,10Mbit,1Mbit
    RATE=28Kbit
    WEIGHT=2Kbit
    PRIO=5
    RULE=:20/0xfffe,192.168.1.10

    192.168.1.10 의 ftp 다운로드속도를 28kbit 로 제한한다.

    ex4.2) 구루구루 업로드 속도제한

    #cbq-030.guruguruup

    DEVICE=eth0,10Mbit,1Mbit
    RATE=40Kbit
    WEIGHT=4Kbit
    MARK=11
    PRIO=5
    RULE=192.168.1.10:9292,

    192.168.1.10 에서 구루구루의 업로드속도를 40kbit로 제한한다. 업스트림속도제어시 ipchains를 이용해 mark를 하라고 했는데 그 mark number를 위와 같이 MARK를 이용해서 반드시 입력해야 한다. 그렇지 않으면 업스트림속도제어는 되지 않는다.

    이제 각 구문의 역할을 알아보자.

  • DEVICE=<ifname>,<bandwidth>[,<weight>]
       DEVICE=eth1,10Mbit,1Mbit

    <ifname> 은 제어할 인터페이스 이름이다. 위의 네트워크예에서 언급했듯이 여기서는 다운스트림은 eth1, 업스트림은 eth0이다.
    <bandwidth> 는 디바이스의 물리적 대역폭이다. 즉, 이더넷은 10Mbit 혹은 100Mbit, arcnet은 2Mbit이다.
    <weight> 는 <bandwidth>에 비례하는 튜닝 파라미터로서 간단히 다음과 같이 계산한다.

    <weight> = <bandwidth> / 10

  • RATE=<speed>
       RATE=1Mbit

    제어할 속도를 지정한다. 단위는 Kbit, Mbit 혹은 bps, Kbps, Mbps 단위이다. 보통 우리가 사용하는 단위는 KByte 이므로 잘 계산하도록 한다. 1 Byte = 8bit 이다.
  • WEIGHT=<speed>
       WEIGHT=500Kbit

    RATE에 비례하는 튜닝 파라메터로서 WEIGHT = RATE / 10 으로 계산해서 입력한다.

  • PRIO=<1-8> 기본값 5
       PRIO=5

    클래스 트래픽의 우선권으로 숫자가 높을수록 우선권이 낮다. 5정도면 좋다.
  • RULE=[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]]

    트래픽에 대한 규칙을 만든다. 설정파일당 여러개의 RULE 항목을 둘 수 있다.
    예를 들면:
    • RULE=10.1.1.0/24:80
      네트워크 10.1.1.0 내 포트80으로 가는 트래픽을 선택.
    • RULE=10.2.2.5
      호스트 10.2.2.5상의 모든 포트로 가는 트래픽 선택.
    • RULE=10.2.2.5:20/0xfffe
      호스트 10.2.2.5의 20,21포트로 가는 트래픽 선택.(ftp)
    • RULE=:25,10.2.2.128/26:5000
      포트 25에서 네트워크 10.2.2.128 네트워크내 포트 5000으로 가는 트래픽을 선택.
    • RULE=10.5.5.5:80,
      호스트 10.5.5.5의 포트 80에서 나가는 트래픽을 선택.
  • MARK=<mark>
       MARK=10

    mark 숫자는 십진수이며 설정파일당 여러개를 지정할 수 있다. 업스트림속도제어시 필수이며 ipchains로 반드시 미리 설정해 주어야 한다. 이외에도 많은 옵션이 있다. 이 중 DEVICE, RATE, WEIGHT는 필수항목이다. 더 자세한 것은 스크립트내 앞부분의 주석을 참고하도록 한다.

    실행은 cbq.init start 로 하며 cbq.init 만 실행하면 실행에 대한 여러 옵션이 나온다.

    # cbq.init
    Usage: cbq.init {start|compile|stop|restart|timecheck|list|stats}

  • start : 스크립트를 실행한다.
  • compile : 실행은 하지않고 tc를 이용해 cbq.init가 설정파일대로 만들어낸 구문들을 보여준다. 스크립트가 실제로 어떻게 작동되는지 알 수 있는 분석에 편리한 명령이다.
  • stop : 스크립트 실행을 멈춘다.
  • restart : 스크립트 재시작.
  • timecheck : TIME 명령을 줬을때 실행.
  • list : 실행했을때 디바이스에 대해 적용된 각종 클래스, 룰을 보여준다.
  • stats : list와 비슷하게 현재 상태를 보여준다. 총 트래픽양과 얼마나 필터를 통과했는지 등에 대해 보여준다.

    5. htb.init 를 이용한 속도제어

    htb.init는 위에서 언급했듯이 cbq.init를 htb용으로 개량한 것으로 사용법 역시 비슷하다. htb설정파일은 /etc/sysconfig/htb 에 놓으면 되며 역시 cbq와 비슷하게 HTB_PATH 부분을 고치면 설정파일의 위치를 바꿀 수 있다. 실행방법 역시 동일하지만 설정시 몇가지 다른 점이 있다. htb.init의 설정파일명형식은 다음과 같다.

    <ifname>-<clsid>(:<clsid>)*<description>

  • <ifname> 은 인터페이스이름. 즉, eth0, eth1과 같은 네트워크 인터페이스의 이름이다.
  • <clsid> 는 클래스 ID로서 16진수이며 2부터 FFFF까지의 범위를 갖는다. 콜론뒤에 클래스 ID가 정의되면 뒤의 ID가 그 설정파일의 클래스 ID임을 나타낸다. (ex. eth0-2:10.www   이 경우 클래스 ID는 뒷자리의 10) 뒷자리 <clsid>앞의 <clsid>는 부모 클래스의 클래스 ID이다. 순서를 유지하기 위해 부모 클래스는 항상 자식 클래스먼저 생성되며 작성시 루트 클래스에서 마지막 클래스까지 완전한 <clsid>패스를 포함시키는게 좋다.
  • <description>에는 클래스에 대한 간단한 설명을 적으면 된다.

    eth0-2
    eth0-2:3
    eth0-2:3:4
    eth1-2.root

    디바이스 eth0 에 대한 root 클래스 id 2
    디바이스 eth0 에 대한 부모클래스 id 2, 자식클래스 id 3
    디바이스 eth0 에 대한 부모클래스 id 3, 자식클래스 id 4
    디바이스 eth1에 대한 root 클래스 id 2

    실제 예를 들어보자. (htb.init 주석 중에서)

    ex5.1) 총 대역폭 5Mbit 인 리눅스서버가 있다. 이 서버에서 웹서버 트래픽으로는 5Mbit, SMTP 트래픽은 3Mbit, 그리고 나머지(분류되지않은 트래픽)는 1Kbit로 제한하고 싶다. 사용되지 않는 대역폭이 있을 경우 SMTP와 분류되지않은 트래픽중에서 공유하도록 하고 싶다.

    "총 대역폭"은 5Mbit의 최대대역폭을 가진 하나의 top-level 클래스라는 것을 의미한다. top-level 클래스하에 세 개의 자식 클래스가 있다.

    첫째, 웹서버 트래픽 클래스는 5Mbit의 대역폭을 사용하도록 할당받는다.
    둘째, SMTP 트래픽 클래스는 3Mbit의 대역폭을 할당받고 사용되지않는 대역폭이 생길시 사용할 수는 있으나 대역폭 5Mbit를 초과해서는 안된다.
    마지막으로 셋째, 분류되지않은 트래픽은 1Kbit의 대역폭을 할당받고 사용되지않는 대역폭을 빌려와서 사용할 수 있으나 5Mbit를 초과해서는 안된다.모든 클래스에 요청이 들어올때 각 클래스의 기본 속도에 비례해서 대역폭을 공유하게 된다. 남는 대역폭이 생길때도 마찬가지로 기본속도에 비례해서 대역폭을 공유하게 된다.

    이 시나리오에 대한 설정파일들은 다음과 같다.

    #eth0
    DEFAULT=30
    R2Q=100

    #eth0-2.root
    # root class containing total bandwidth
    RATE=5Mbit
    BURST=15k

    #eth0-2:10.www
    # class for outgoing WWW traffic
    RATE=5Mbit
    BURST=15k
    LEAF=sfq
    RULE=*:80,

    #eth0-2:20.smtp
    # class for outgoing SMTP traffic
    RATE=3Mbit
    CEIL=5Mbit
    BURST=15k
    LEAF=sfq
    RULE=*:25

    #eth0-2:30.dfl
    # default class for unclassified traffic
    RATE=1Kbit
    CEIL=5Mbit
    BURST=15k
    LEAF=sfq

    다른 간단한 예제를 들어보면,

    ex5.2) ftp 다운로드 속도제한

    #eth1-2.host10ftp

    RATE=32kbit
    BURST=15k
    LEAF=sfq
    PRIO=5
    RULE=:20/0fffe,192.168.1.10

    host 192.168.1.10에 대한 ftp 다운로드 속도를 32kbit 로 제한한다.

    ex5.3) ftp 업로드 속도제한

    #eth0-2.host10www

    RATE=28kbit
    BURST=15k
    LEAF=sfq
    PRIO=2
    MARK=11
    RULE=192.168.1.10,:20/0xfffe

    호스트 192.168.1.10의 ftp 업로드 속도를 28kbit로 제한한다. 업로드이므로 mark를 해줘야하며 여기서는 11로 돼있다.

    다른 프로그램에 대해선 적당히 변경해주면 된다. htb.init의 경우 속도제어를 해줄 인터페이스에 대한 파일이 기본적으로 있어야한다. 그 다음 각각의 프로그램에 대한 설정파일을 만든다.

    #eth0

    DEFAULT=30
    R2Q=100

    eth1의 경우도 똑같이 만들어주면 된다.ex5.1 시나리오예제처럼 계층을 만들지 않고 간단하게 하고 싶다면 *.root 파일은 만들지 않아도 된다.

    htb의 경우 클래스에 부모클래스와 자식클래스가 있다고 했는데 부모클래스의 속도를 지정하고 그 밑의 자식클래스에 대역폭을 나눠주는것이 가능하다. 그리고 cbq와 달리 htb는 다른 클래스에 대역폭을 한도내에서 빌려주는것이 가능하다.(ceil) 시나리오 설정파일을 살펴보면 알 수 있다. 자세한 사항은 htb홈페이지 유저매뉴얼을 보기바라며 빠른 시간내에 간단한 요약문을 올리도록 하겠다.

  • 댓글 없음:

    댓글 쓰기