On Jan 11, 2006, at 7:24 PM, David S. Madole wrote:

From: "Dan Joumaa" <[EMAIL PROTECTED]>

I'm trying to code a software gateway with divert sockets. So far basic things are working, but the net stack constantly resets the connection whenever a SYN-ACK is sent to it.

Any ideas on how to stop the net stack from resetting my connections, preferably programmatically?

I think you are doing something wrong, either not diverting packets that should be, or reinjecting packets from your code that are incorrect in some way.

Without seeing the ipfw rules or code, there's not much else that can be said.

David



Here's the rules:

00001 divert 4747 tcp from 192.168.1.6 to any in
00001 divert 4747 udp from 192.168.1.6 to any in

The following rules are added dynamically when my client sends a packet to a server so we can get it back on the divert socket. In this case, it would be:

00001 divert 4747 tcp from 205.166.76.216 to any in
00001 divert 4747 udp from 205.166.76.216 to any in

First thing, I receive the packets from the divert socket.

...
    if( (datagramlen = recvfrom( sock->ipfd, buffer, buflen, 0x0,
(struct sockaddr *)&sin, &sinlen )) < 0 )
        (void)fprintf( stderr, "Failed to receive packet. Error: %i\n",
                       errno );
...

If it is from my client, I add the destination host the client wants to talk to as a divert rule to the IPFW...

    entry->version = IP_FW_CURRENT_API_VERSION;
        entry->fw_number = 1;
    entry->fw_src.s_addr = htonl(host);
        entry->fw_smsk.s_addr = ~0;
    entry->fw_prot = IPPROTO_TCP;
    entry->fw_flg = IP_FW_F_DIVERT|IP_FW_F_IN;
    entry->fw_un.fu_divert_port = DIVERTSOCKET_PORT;
        (void)memcpy( entry->fw_in_if.fu_via_if.name, sock->dev, FW_IFNLEN );
        entry->fw_in_if.fu_via_if.unit = -1;
    if( setsockopt( sock->fwfd, IPPROTO_IP, IP_FW_ADD, entry,
                    sizeof(struct ip_fw) ) < 0 ) {
(void)fprintf( stderr, "Failed to add entry to filter. Error: %i\n",
                       errno );
        return (-1);
    }

... modify the packet for sending ...

                ip_hdr->ip_src.s_addr = htonl( thisIP );
                /* checksuming code below */

... and send it through a raw socket.

    sin.sin_family = AF_INET;
    sin.sin_port = 0;
    sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
    if( (datagramlen = sendto( socket->fwfd, buffer, buflen, 0x0,
(struct sockaddr *)&sin, sizeof(sin) )) < 0 ) (void)fprintf( stderr, "Failed to send packet. Error: %i\n", errno );

If it's from someone outside the LAN, modify it for forwarding to the client...

                ip_hdr->ip_dst.s_addr = htonl( clientIP );
                
                ip_hdr->ip_sum = 0;
                ip_hdr->ip_sum = htons( in_cksum( (u_short *)ip_hdr,
                                                                                
  sizeof(struct iphdr) ) );
                /* checksuming code below */

And send it through a raw socket.

All in all, that's really what it is. This seems to work with normal HTTP requests, but fails to work with establishing a connection on HTTPS. :/

--ness

_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to