Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Jan 2006 21:06:08 -0700
From:      Dan Joumaa <nessup@gmail.com>
To:        David S. Madole <david@madole.net>, julian@elischer.org
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Telling BSD to stop resetting the connection!
Message-ID:  <e0d9dbf0dbfc36a2fd4659a9a4004816@gmail.com>
In-Reply-To: <096b01c6171f$62711140$c3e7a8c0@david>
References:  <ca819c8f74a6f6518ac6f2b588f56de8@gmail.com> <096b01c6171f$62711140$c3e7a8c0@david>

next in thread | previous in thread | raw e-mail | index | archive | help

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

> From: "Dan Joumaa" <nessup@gmail.com>
>>
>> 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?e0d9dbf0dbfc36a2fd4659a9a4004816>