udp redirector?

hunt417의 이미지

안녕하세요. 이런공간이 있는줄은 첨 알았습니다.반갑네요.

IP forwarding 이 정확한 용어가 될지는 모르겠지만..
udp redirector를 구현하고자 합니다.

통신이 잘되는 udp 서버와 클라이언트의 중간에 redirector를 구성하여
로드 밸런싱을 하고자 합니다. redirector는 결국 클라이언트로부터 udp 패킷을 전달받아 등록된 다수의 서버로 일정규칙에 의해서 배분해 주는 모듈입니다.

근데.. 문제는 서버에서 클라이언트로 응답시 redirector를 거치지 않고 바로 클라이언트로 응답이 가도록 하는 방식을 취하고자 합니다.
제가 생각한 방법은 redirector에서 클라이언트에서 전달받은 패킷을 서버로 전달하는 순간 소스 ip를 자신의 주소로 취하지 않고 전달받은 원 패킷의 ip를 가져와서 넣어주면 된다고 생각합니다. 그런데, 내공이 부족해서인지 어떻게 해줘야 할지를 모르겠네요.. ^^

ip address 추출이야 간단하지만, ip 헤더에 접근해서 소스 ip를 바꿔치기 할 방법을 모르겠습니다.
raw socket을 써야 하나요? 한번도 써본적이 없어서.. -.-
고수님들 조언이나 그저 생각나는 거 하나라도 얘기해주신다면 저에게는 큰 도움이 될성 싶습니다. 관련 자료도 있으면.. 좀~~

제가 염치가 좀 없네요..ㅋㅋ

charsyam의 이미지

raw 소켓을 쓰시면 됩니다. 내부적으로는 가능한데,

보통 외부와의 서버로 로드밸런싱을 하기는 힘들겁니다.

패킷의 유실 여부를 떠나서, 보통 ISP에서 IP가 다른것은

막아버리더군요. 쩝... raw 소켓에서 IP_HDR 어쩌고 옵션을

이용하시면 될껍니다. 그럼(아닐수도... 기억이 나빠서리)

=========================
CharSyam ^^ --- 고운 하루
=========================

hunt417의 이미지

그럼.. raw socket으로 가닥을 잡고 해나가면 되겠군요.

조언 감사하구요. 완성이 되면 결과물도 올려드리겠습니다.
(언제가 될까요??? ^^)

그날을 위해서

swhong의 이미지

왜 IP주소를 바꾸어 주어야 하지요?

제가 님께서 쓰신 내용을 이해한 바로는 님께서 IP헤더가 routing될때마다 바뀐다고 오해하시고 있는 것으로 생각됩니다.

IP header의 source ip field는 바뀌지 않지요...

즉 datalink의 header부분만 교체되고, ip header는 교체되지 않습니다.

제가 생각을 하기에는 redirector를 통해 들어간 패킷을 처리하여 reply를 줄때 다시 redirector를 거치지 않게 하려면, reply를 보내는 gateway를 따로 설정해 주어야 하겠지요...

제가 님의 글을 오해했는지도 모르겠습니다.

- by swhong in jgdr.net -

hunt417의 이미지

udp ( 트랜잭션 계층 ) 게이트웨이를 만드려다가 발생한 문제인데요. 일반적인 게이트웨이(redirector) 처럼 한다면 궂이 ip헤더에 직접 접근할 일이 없는데, 응답을 줄때는 그 게이트웨이를 통하지 않고 바로 클라이언트에 응답을 주려고 시도하기 때문에 발생하는 문제입니다.
제 구상으로는 ip 헤더의 ip와 포트만 원래 전달받은 클라이언트의 주소로 바꾸어도 가능할것이라고 생각되어.. ( spoofing 프로그램이 이런식으로 구성된다고 하는데 정확하게는 저도 잘.. -.- )

라우팅과는 그닥 연관이 없을것으로 생각됩니다..

unix network programming 책을 보고 있는데 얼핏 보기로는 datalink access접근과 관련이 있을지도 모르겠습니다. 차차 진행해보면 결과가 나오리라 생각됩니다.

어디 괜찮은 자료나 사이트 없나요? 맘이 급해서 책만 이리저리 뒤집고 있네요..ㅎㅎ

그날을 위해서

고도리의 이미지

패킷을 건드릴때 주로 raw socket을 많이 사용을 합니다.
하지만 raw socket은 약간의 문제가 있습니다.

제가 libpcap등을 사용할때 느낀거지만 packet을 가로챌수는
있으나, 가로챈 패킷이 커널로 가는 것은 막지를 못합니다.

무슨 얘기냐 하면 ip packet의 복사본을 보는 것이지 실제
그걸 완전히 가로챈게 아니기 때문입니다.
(제가 raw socket고수가 아니라서 여기까지가 한계인데
혹시 완전히 가로챌 수 있는 방법이 있으면......^^)

퍼포먼스도 커널보다는 조금 안좋을 거고요....

커널단 프로그램이 가장 수월할 겁니다.

udp일 경우는 조금 쉽게 구현할 수 있을 겁니다.
(TCP보다는요)

의외로 몇 줄 정도면 redirection을 할 수 있을겁니다.

net/ipv4/ip_input.c의 ip_rcv()함수로 모든 패킷이 올라가는데
거기서 가로채기 하면 될겁니다.

까다로운 부분은 checksum부분인데 리눅스 커널의 checksum함수가
되게 사용법이 까다롭습니다.

다른데서 사용된 코드를 example로 해서 보면 큰 어려움이 없을테고요.

커널도 공부할겸 함 해보시는 것도....

그럼....

서명.....음, 서명이라...

아싸!!! Three Go!

hunt417의 이미지

rawsocket을 이용해서 ip header(udp header 포함되겠죠)를 불러들인 후
각 헤더를 적절한 값으로 채운후 보내니 잘 됩니다. 소켓 선언할때도 좀 달리해줘야 ...

정말 이해가 안가는건 recvfrom 함수에서 6번째 파라미터인 socklen_t를 초기화 해줘야 source 주소 구조체를 받아올수 있다는 점입니다. 정말 황당합니다.
다른 프로그램에서는 초기화 안해줘도 잘 받아왔는데... 끙~~
main함수내의 변수는 자동으로 초기화 되나요? 그건 아니라고 생각되는데...

< 소스 >
소켓 선언부분..

        wrsrcauthfd = socket(AF_INET,SOCK_RAW,IPPROTO_UDP) ;
        setsockopt(wrsrcauthfd , IPPROTO_IP,IP_HDRINCL , &on , sizeof( on ) ) ;

recvfrom과 sendto 부분..
        socklen_t       len = 16 ; /* socket len ?? if not assigned , cannnot get source address */
        int     nReceived = 0 ;
        memset( buf , 0 , MAXBUFLEN) ;

        nReceived = recvfrom(srcfd ,buf , MAXBUFLEN ,0, (struct sockaddr *) &cliaddr,&len) ;

        if ( nReceived ) {
                char    srcIP[16] ,dstIP[16];
                memset(srcIP,0,16) ; memset(dstIP,0,16) ;

                pLog->AddHex((char      *) &cliaddr , 16) ;
                pLog->AddHex((char      *) pTargetSA , 16) ;
                memset(packet,0x00,sizeof(packet)) ;

                strcpy( srcIP , inet_ntoa(cliaddr.sin_addr)) ;
                strcpy( dstIP , inet_ntoa(((sockaddr_in *)pTargetSA)->sin_addr)) ;

                makeRawHeader(packet,nReceived
                        ,srcIP, ntohs(cliaddr.sin_port)
                        ,dstIP, ntohs(((sockaddr_in *) pTargetSA)->sin_port)) ;
                memcpy(packet + 28 , buf , nReceived ) ;
                pLog->AddHex(packet , nReceived + 28 ) ;
                if ( sendto(writefd , packet , 28+nReceived, 0 ,
                        pTargetSA, sizeof(struct sockaddr))  < 0 )
                {
                        return -1 ;
                }

헤더 만드는 부분..

        typedef struct _IPHEADER {
                char    verlen ;
                char    tos ;
                short   totallength ;
                char    identification[2] ;
                char    fragmentoffset[2] ;
                char    ttl ;
                char    protocol ;
                unsigned        short   headerchecksum ;
                unsigned        long    srcip ;
                unsigned        long    dstip ;
        } IPHEADER ;

        typedef struct _UDPHEADER {
                unsigned        short   srcport ;
                unsigned        short   dstport ;
                unsigned        short   udplength ;
                unsigned        short   headerchecksum ;
        } UDPHEADER ;

        IPHEADER        iphead ;
        memset(&iphead,0x00,sizeof(IPHEADER)) ;
        iphead.verlen = 0x45 ;  /* IPv4 , headerlen = 20 ( 4 * 5 ) */
        iphead.totallength = htons(datalen + UDPHEADERLEN + IPHEADERLEN) ;
        iphead.fragmentoffset[0] = 0x40 ;
        iphead.fragmentoffset[1] = 0x00 ;
        iphead.ttl = 0x40 ;
        iphead.protocol = IPPROTO_UDP ; /* udp - 0x11*/
        iphead.srcip = inet_addr(srcIP) ;
        iphead.dstip = inet_addr(dstIP) ;

        UDPHEADER       udphead ;
        memset(&udphead, 0x00 , sizeof(UDPHEADER)) ;
        udphead.srcport = htons(srcPort) ;
        udphead.dstport = htons(dstPort) ;
        udphead.udplength = htons(datalen + sizeof(UDPHEADER)) ;


        memcpy(buf , &iphead , sizeof(IPHEADER)) ;
        memcpy(buf + sizeof(IPHEADER) , &udphead , sizeof(UDPHEADER)) ;

그날을 위해서

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.