# Using PF to divert, then rdr



## dcole (Nov 1, 2012)

Hello,

I have a couple of scenarios I am curious about. If I have a PF rule to divert ALL tcp traffic to a IPPROTO_DIVERT socket, that is doing a recvfrom() and a sendto().

And another rule immediately following that PF rule that is doing a rdr of ALL tcp traffic to another network interface.

Can I be assured that if I have a SOCK_STREAM socket accept() traffic from the interface the rdr is pointing to, TCP connections will be accepted on that socket in the order they passed through the divert socket?

My goal here is to be able to be able to sniff or modify packets with the divert, reinject them, and have them then go through a normal TCP connection acceptation with the stream socket, this way I can read and write back and forth between the server and the client. I want to be able to correlate the packets I detected in the divert socket with connections established in the stream socket. 

Thanks in advance


----------



## expl (Nov 2, 2012)

dcole said:
			
		

> I have a PF rule to divert ALL tcp traffic to a IPPROTO_DIVERT socket



Problem with this is that divert sockets are extremely inefficient due to packages being copied to and from userspace memory. It can work well with very specific PF rules but for all traffic its an over kill in terms of performance.



			
				dcole said:
			
		

> Can I be assured that if I have a SOCK_STREAM socket accept() traffic from the interface the rdr is pointing to, TCP connections will be accepted on that socket in the order they passed through the divert socket?



Most likely, but you have to make sure you re-inject those packets in your divert socket or they will be lost.



			
				dcole said:
			
		

> My goal here is to be able to be able to sniff or modify packets with the divert, reinject them, and have them then go through a normal TCP connection acceptation with the stream socket, this way I can read and write back and forth between the server and the client. I want to be able to correlate the packets i detected in the divert socket with connections established in the stream socket.



When it comes to TCP you should not single out a specific package for rejection because this will cause lag and the package to be resent by parent host and if you keep rejecting it, the connection will hang. So you either drop connection as whole or let every package to pass. You could modify them to some extend, but it's not hard to break the underlying protocol.


----------



## dcole (Nov 2, 2012)

So I was able to get the divert socket working, and I can see with tcpdump the packet going in, and going out on that interface. I am trying to modify the tcp destination port, and destination IP address.

Do I need to recalculate the checksum for IP and TCP for this to work? I have been trying to get that working, and I keep seeing a reset packet after the packet leaves the divert rule.


----------



## expl (Nov 2, 2012)

Yes, you definitely need to recalculate and change the checksum.


----------



## dcole (Nov 4, 2012)

Well, I keep running into one road block after another. Read in the manpage of divert


```
The port part of the socket address passed to the sendto(2) contains a
     tag that should be meaningful to the diversion module.  In the case of
     ipfw(8) the tag is interpreted as the rule number after which rule pro-
     cessing should restart.
```

Does this apply for PF as well? The problem is, PF wont let me do a redirect after changing something about the packet with the divert-to because of the order of the PF.conf file can't be changed. So setting the tag to zero doesn't do a full reprocessing (including rdr), it just does the filtering rules. 

I think I would have this problem solved if I could do this scenario:


Divert packet, to change the port to a specified range 5000:10000 let's say
Create a socket with the specified port for that packet that was diverted
redirect packet when it re-enters the stream to the interface my socket is listening on ports 5000:10000


In my existing scenario, I was changing the IP address to that of my listening interface, as well as the port number that I had created the socket on, to try to accept the connection. This will never work because the SYN/ACK accept is sent from the wrong IP address. So I need to leave the IP address unmodified. I am assuming when I use RDR in my PF.conf, the kernel keeps track of true destination/redirected destination, so that you can still open a SOCK_STREAM connection. This is the functionality I'd like to recreate. 

I know little of IPFW..will it let me create a scenario like htis more easily? I was just using PF becaues I already had some existing rules to do some other things.


----------



## expl (Nov 5, 2012)

Can you perhaps write what are you trying exactly to do in a single post? Its very confusing to understand why do you need divert sockets if you only want to redirect traffic.


----------



## dcole (Nov 8, 2012)

I am trying to determine where traffic is going even if it has been redirected/nat'd

Is it possible to make a normal SOCK_STREAM connection of a previously nat'd connection, and look up the information about what the original destination and source addresses were before the NAT?

I was noticing that under IOCTL that there is a DIOCNATLOOK function that I have been tinkering with, but I havent quite gotten the sample program to work yet. Maybe there is an easier way than what I was trying to do.


----------

