Re: Divert socket issues.

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Fri, 1 Mar 2013 17:23:49 +0400
On Fri, Mar 01, 2013 at 11:44:48AM +1100, Varun Chandramohan wrote:
V> I sent this email to net group, unfortunately I got no response. Iam sorry
V> if that was the wrong group. Trying it again in this group. I wrote a small
V> program using divert sockets to capture packets using ipfw at outgoing. The
V> packets that are captured is for application mangling (mostly http headers)
V> and resent it back to browser. That means I need to reinject it back in
V> incoming instead of outgoing. I believe this is possible based on what is
V> said in the man pages.
V> 
V> Man page:
V> 
V> if sendto(2) is used with a destination IP address of INADDR_ANY, then the
V> packet is treated as if it were outgoing, i.e., destined for a non-local
V> address.  Otherwise, the packet is assumed to be incoming and full packet
V> routing is done.
V> 
V> In the latter case, the IP address specified must match the address of some
V> local interface, or an interface name must be found after the IP address.
V>  If an interface name is found, that interface will be used and the value
V> of the IP
V> address will be ignored (other than the fact that it is not INADDR_ANY).
V>  This is to indicate on which interface the packet ``arrived.''
V> 
V> According to these instructions, I want my packet In-bound so I set my
V> local ip address for the sendto data structure using the below code.
V> 
V> ssize_t
V> divert_get(int sd, struct sockaddr_in *sa, char *pkt_buf, int buflen){
V>     ssize_t len;
V>     unsigned int addrlen;
V> 
V>     addrlen = sizeof(*sa);
V>     len = recvfrom(sd, pkt_buf, buflen, 0,
V>                    (struct sockaddr *) sa, &addrlen);
V>     if(len == -1) {
V>         bps_log(LOG_ERR, "Unable to recieve message from socket", errno);
V>     }
V>     return(len);}
V> 
V> 
V> /* addr is passed &sa from the above code */
V> rebuild_header(void *ptr, struct sockaddr_in *addr) {
V> ssize_t new_len = change_header(ptr);struct ip *ip = (struct ip*)ptr;
V> /* this is to divert it to input instead of output */
V> addr->sin_addr.s_addr = ip->ip_src.s_addr;
V> 
V>  /* Recompute checksums */
V>   ip->ip_len = htons(new_len);
V> 
V>    cal_ip_cksum(ptr);
V>    cal_tcp_cksum(ptr);
V> 
V>    if(divert_send(sd, addr, ptr, pkt_len) < 0) {
V>       printf("No data sent from divert socket %d", errno);
V>     }
V> }
V> 
V> 
V> I expect the packet to now be inbound but my application is not getting the
V> response sent by me. The possible case could be kernel dropping the packet.
V> I even set the port number which is the rule I want to match for example, I
V> have only two rules 1 and 65535. I tried setting port number to 0,1 and
V> even 65535 but still the kernel drops the packet.
V> 
V>  addr->sin_port = htons(65535);
V> 
V> sento seems to work fine but the packet does not go through. If I re-inject
V> the packet back in the outgoing path (same place I took the packet) things
V> seem to work fine. Can someone please tell me whats wrong here? I don't
V> seem to understand. The man page is not very clear. I looked a bit into
V> divert code and it seem to call ip_input() for the packet I re-injected. If
V> thats the case, won't my packet get dropped because it has src address as
V> my local address (it expects it to be other way around if server has
V> responded)? Can someone please clarify this? If I have to still do it, do I
V> need to modify TCP/IP header fields as well?

Right, the packet is dropped due to its destination in IP header doesn't
match any local addresses.

Rewriting IP header to your destionation address of any random TCP packet
won't be enough, though, since in this case packet still would be dropped
due to it doesn't match any existing connection.

-- 
Totus tuus, Glebius.
Received on Fri Mar 01 2013 - 12:25:03 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:35 UTC