2014-02-26 9 views
0

얼마 전 Ashwin Kashyap (http://www.research.rutgers.edu/~ashwink/misc_projs/ebt_vnat.html)의 vnat 모듈을 기반으로 ebtables 모듈을 구현했습니다. 모듈은 vlan 태그를 제거하고 vlan id를 nf 표시로두기 위해 broute 테이블의 BROUTING 체인에서 사용할 수 있습니다. 또한 모듈은 NAT 테이블의 POSTROUTING 체인에 nf 표시 값을 기반으로 VLAN 태그를 추가 할 수 있습니다. 모듈은 브리지 된 트래픽에 대한 작업에 아무런 문제가 없습니다. 시스템은 견고하고 안정적입니다. tproxy 차단을 믹스에 추가하자 마자 문제가 시작됩니다. 이 작업으로 인해 커널 패닉이 발생합니다. 필자는 트래픽 스트림이 몇 분만 지나면 첫 번째 패킷 이후에 커널 패닉이 발생하지 않는다는 사실을 강조합니다. SKB를 망가 뜨리는 방식이 L3 + 처리를 위해 충분히 깨끗하지 않은 것 같습니다. BTW 2.6.32 커널에서 일하고 있습니다. 아래 의견 모듈의 중요한 부분을 찾아주세요 :맞춤 ebtables 모듈 && skb 조작 && 커널 패닉

// code for adding vlan tag based on skb->mark value 
if (!skb_make_writable(skb, 0)) 
    return EBT_DROP; 

if(skb->mark > 0){ 
    // maybe we should always seek VLAN_HLEN+ETH_HLEN instead of using condition? 
    if (skb_headroom(skb) < (skb->mac_len == 0 ? VLAN_HLEN + ETH_HLEN : VLAN_HLEN)) { 
    struct sk_buff *sk_tmp = skb; 
    skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); 
    kfree_skb(sk_tmp); 

    if (skb == NULL) { 
     return EBT_DROP; 
    } 
    } 

    // we need 4 more bytes for 802.1q header, so push!...I can almost see the head(er) 
    skb_push(skb, VLAN_HLEN); 

    skb->mac_header-=VLAN_HLEN; 
    skb->network_header-=VLAN_HLEN; 
    skb->transport_header-=VLAN_HLEN; 
    veth = (struct vlan_ethhdr *) eth_hdr(skb); 

    // move dst/src mac addresses (12b of header) 4 bytes back to make room for 
    // 802.1q header 
    memmove(skb->head + skb->mac_header, skb->head + skb->mac_header + VLAN_HLEN, 12); 

    // fill 802.1q header 
    veth->h_vlan_proto = __constant_htons(ETH_P_8021Q); 
    veth_TCI = skb->mark & 0xfff; 
    veth->h_vlan_TCI = htons(veth_TCI);  
} 

// code for stripping vlan tag and putting it into skb->mark value 
veth = (struct vlan_ethhdr *)eth_hdr(skb); 
if(veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)){ 

    if (!skb_make_writable(skb, 0)) 
    return EBT_DROP; 

    // determine vlan id 
    vid=(ntohs(veth->h_vlan_TCI) & 0xfff); 
    mark = vid; 

    // copy dst/src mac addresses (12b) 4 bytes fwd, so it covers 802.1q header 
    memmove(skb->head + skb->mac_header + VLAN_HLEN, skb->head + skb->mac_header, 12); 

    // adapt header pointers 
    skb->mac_header+=VLAN_HLEN; 
    skb->mac_len = ETH_HLEN; 
    skb->network_header+=VLAN_HLEN; 
    skb->transport_header+=VLAN_HLEN; 
    skb->data += VLAN_HLEN; 
    skb->len -= VLAN_HLEN; 

    eth = eth_hdr(skb); 
    skb->protocol=eth->h_proto; 
} 
skb->mark=mark; 

내가 어떤 포인터에 대한 감사하게 될 거라고 (만큼 그들은 적어도 긴 64 비트이기 때문에). 감사!

답변

0

코드에서 MAC 헤더를 변경하여 802.1q 헤더를 추가하거나 제거합니다. 이제 내가 잘못 생각할 수도 있지만 포인터를 네트워크로 옮기고 레이어 헤더를 전송해야하는 이유는 무엇입니까?

MAC 헤더가 확장되어 skb 헤드 룸에 들어가기를 기대하지만 나머지 패킷은 어느 경우에도 영향을받지 않습니다. 네트워크 및 전송 헤더를 이동하면 상위 계층 (3+)이 잘못된 처음 4 바이트를 읽습니다.

(NB 나는 대답이 아니라 내가 옳다는 자신감이 없기 때문에이 글을 답장으로 작성했을 것이다. 그러나 나는 최근에 ebtable을위한 VLAN 태그 변환 모듈을 연구하고 있는데 이것은 내가 처음이다. 그래서 내 명성이 충분히 높지는 않습니다.)