Fwd: Modifying TCP packets with libnetfilter_queue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks for the pointers, am still having problems sadly.

Does it matter where I intercept the packets? As a dev system, I have
been using a rule like: iptables -t filter -I OUTPUT -s ipaddress -j
QUEUE

This rule certainly picks up the packets, interestingly enough the
checksum is equal to zero, which according to the rfc is correct, this
I think is where my problem is coming from. Should I be queuing direct
from the wire? am wondering if the linux tcp/ip stack is playing games
with me ^_^

On Thu, Aug 27, 2009 at 5:34 PM, Kuzin Andrey<kuzinandrey@xxxxxxxxx> wrote:
> MLm> Hi,
> MLm> I am attempting to adjust contents of tcp packets using the nf queue
> MLm> system, the queue part is working as I expected, however I am running
> MLm> into problems recalculating the tcp checksum. At the moment, the
> MLm> packet isnt being changed, and I am simply reading the checksum, then
> MLm> trying to regenerate it, these values arent matching and I am at a
> MLm> loss as to where I am going wrong.
> MLm> Any help or suggestions please? I am at a loss
>
> Try this code stolen from tcpdump and other cool stuff.
>
> /*
>  * IP header checksum.
>  * don't modifiy the packet.
>  */
> u_short
> in_cksum(const u_short *addr, register u_int len, int csum)
> {
>        int nleft = len;
>        const u_short *w = addr;
>        u_short answer;
>        int sum = csum;
>
>        /*
>         *  Our algorithm is simple, using a 32 bit accumulator (sum),
>         *  we add sequential 16 bit words to it, and at the end, fold
>         *  back all the carry bits from the top 16 bits into the lower
>         *  16 bits.
>         */
>        while (nleft > 1)  {
>                sum += *w++;
>                nleft -= 2;
>        }
>        if (nleft == 1)
>                sum += htons(*(u_char *)w<<8);
>
>        /*
>         * add back carry outs from top 16 bits to low 16 bits
>         */
>        sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
>        sum += (sum >> 16);                     /* add carry */
>        answer = ~sum;                          /* truncate to 16 bits */
>        return (answer);
> }
>
> static int tcp_cksum(register const struct ip *ip,
>                     register const struct tcphdr *tp,
>                     register u_int len)
> {
>        union phu {
>                struct phdr {
>                        u_int32_t src;
>                        u_int32_t dst;
>                        u_char mbz;
>                        u_char proto;
>                        u_int16_t len;
>                } ph;
>                u_int16_t pa[6];
>        } phu;
>        const u_int16_t *sp;
>
>        /* pseudo-header.. */
>        phu.ph.len = htons((u_int16_t)len);
>        phu.ph.mbz = 0;
>        phu.ph.proto = IPPROTO_TCP;
>        memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
>        if ( (ip->ip_hl & 0x0f) == 5)
>                memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
>        else
>                phu.ph.dst = ip_finddst(ip);
>
>        sp = &phu.pa[0];
>        return in_cksum((u_short *)tp, len,
>                        sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
> }
>
>
> void recalculate_tcp_checksum(unsigned char *packet)
> {
>    struct ip *ip_packet = NULL;
>    struct tcphdr *tcp_packet = NULL;
>    u_int16_t word16, padd = 0, i, sum = 0, tcp_len;
>    unsigned char *buff;
>    if (!packet) return;
>
>    ip_packet = (struct ip *)packet;
>    tcp_packet = (struct tcphdr *)(packet + (ip_packet->ip_hl << 2));
>    tcp_len = ntohs(ip_packet->ip_len) - (ip_packet->ip_hl << 2);
>
>    sum = tcp_cksum(ip_packet,tcp_packet,tcp_len);
>    tcp_packet->check = sum; //ntohs(sum);
> }
>
>
> Use recalculate_tcp_checksum() on your modified payload in this way:
>
>
>    void *packet;
>    struct ip *ip_packet = NULL;
>    struct tcphdr *tcp_packet = NULL;
>    unsigned char *tcp_packet_content = NULL;
>
> .......
>    ip_packet = ((struct ip *)packet);
>
>    if (ip_packet->ip_p == IPPROTO_TCP) {
>        tcp_packet = (struct tcphdr *)(packet + sizeof(struct ip));
>        tcp_packet_content = (unsigned char *)(packet + sizeof(struct ip) + sizeof(struct tcphdr));
>        tcp_packet_content_size = htons(ip_packet->ip_len) - sizeof(struct ip) - sizeof(struct tcphdr);
>        .......
>        // modify payload...
>        .......
>        // calculate
>        tcp_packet->check = 0;
>        recalculate_tcp_checksum(packet);
>   }
>
> You also can move some of this code to recalculate_tcp_checksum() and
> simply call recalculate_tcp_checksum() without any payload preparations.
>
> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
> Kuzin Andrey  -  kuzinandrey@xxxxxxxxx
> =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
>
>
>



--
Michael Lawson (mshindo)



-- 
Michael Lawson (mshindo)
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux