Telling BSD to stop resetting the connection!

Dan Joumaa nessup at gmail.com
Wed Jan 11 20:06:15 PST 2006


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

> From: "Dan Joumaa" <nessup at 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



More information about the freebsd-hackers mailing list