How to force rerouting of a packet after return to netfilter from NFQUEUE - network-programming

I have a caching application that runs in userspace. Normally, it uses DPDK to interact with the NICs directly without kernel interaction, grabbing packets off of the wire, and either passing them through, generating a response from cache, or in some occasions blocking them. It's transparent to the endpoints, and is written to work on raw packet data straight from the NIC. Notably, I'm not doing normal socket programming here - everything's handled at the packet level, without interaction with the TCP/IP stack.
For reasons that are long and boring, I wanted to add some NAT functionality. As a proof of concept, I was hoping to put a front end on my application using iptables/netfilter. So I did the NAT parts with commands like these:
sudo iptables --table nat --append PREROUTING --in-interface seg1a -j DNAT --to-destination $SERVERIP
sudo iptables --table nat --append POSTROUTING --out-interface seg1b -j MASQUERADE
sudo route add $SERVERIP seg1b
This works well for my purposes. The clients now attach to an interface on my system, but their traffic gets redirected to the server. I'm guaranteed that their traffic passes through my system, so all's good.
But to be useful as a cache, I need to be able to respond to some requests that I get from clients. I had thought I could use NFQUEUE for this, with a small application that reads from the netfilter queue and passes packets to and from my application via IPC. I used an iptables rule like this:
sudo iptables --table mangle --append FORWARD -j NFQUEUE
This works OK as long as my application doesn't respond to anything. But when my cache attempts to respond to something from one of the endpoints, things go wrong. The cache reverses all of the L2-4 headers, manages sequence and ack numbers, etc. But the packets don't get back to the client.
I think what's happening is that routing decisions for the packet were made before it was sent to NFQUEUE. So even though the cache returns something whose source and destination IP addresses are reversed, that's irrelevant for the routing of the packet.
I've tried a number of things to change the routing of my response packets, but nothing seems to work. How does one go about changing the routing on a packet read from netfilter queues? Failing that, is there a good way to just inject packets onto the wire from netfilter queues? If that were doable, I could block the original request and then send the cache's reply as an entirely new thing.
Thanks in advance for any suggestions.

The best answer I came up with for this problem was to open a raw socket and feed it my pre-built packets. Critically, you must create an iptables rule that matches your generated packets and tells netfilter not to do connection tracking. Otherwise, netfilter sees the injected packets and thinks there's a connection collision. It then does port forwarding, so the packets come out with a different port than you put in there!
I built the socket like this:
sid = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
Then, I turned on a couple of options (leaving failure handling out for brevity):
int one = 1;
const int *val = &one;
retval = setsockopt(sid, IPPROTO_IP, IP_HDRINCL, val, sizeof(one));
retval = setsockopt(sid, SOL_SOCKET, SO_MARK, val, sizeof(one));
The first of these tells the kernel that I have the headers already, so no need to try and create them. The second tells the kernel to put a mark value of 1 on every packet sent via the socket, which I can match against in routing or iptables rules.
Later, I built a destination address and used sendto() to send the packet:
retval = sendto(sid, pL3, len, 0, (struct sockaddr *)&daddr, sizeof(daddr));
Finally, I installed a rule telling netfilter not to do connection tracking on TCP packets marked with a 1. Since I had added the sockopt above so that all of my generated packets had this mark, this worked well:
sudo iptables -t raw -I OUTPUT -p tcp -m mark --mark 1 -j CT --notrack

Related

How do i check my nat type using stun? New on this

i want to know my nat type, i was trying with this command "netsh interface Teredo show state" however someone suggested me that i should ie a stun server or client to have a better idea of my nat. But i dont have any idea of this, i just want to have an open nat to play games, so please be patient with me :)
By the way i have enabled DMZ and UPNP on my modem.
Server Name : win1910.ipv6.microsoft.com.
Client Refresh Interval : 20 seconds
Client Port : unspecified
State : qualified
Client Type : teredo client
Network : unmanaged
NAT : symmetric (port)
NAT Special Behaviour : UPNP: Yes, PortPreserving: Yes
I googled for stun clients or servers but they dont have any info on how to install them or use them, like this one https://github.com/moien007/STUN so if someone can help me with an app that is easy to install or some instructions on how to install a stun server or client please.
Thank you very much.
Edit runing stuntcode.exe got this
Result of CTestDataStream: PASS
Result of CTestReader: PASS
Result of CTestBuilder: PASS
Result of CTestIntegrity: PASS
Result of CTestMessageHandler: PASS
Result of CTestCmdLineParser: PASS
Testing detection for DirectMapping
Testing detection for EndpointIndependent mapping
Testing detection for AddressDependentMapping
Testing detection for AddressAndPortDependentMapping
Testing detection for EndpointIndependentFiltering
Testing detection for AddressDependentFiltering
Testing detection for AddressAndPortDependentFiltering
Result of CTestClientLogic: PASS
Result of CTestRecvFromEx(IPV4): PASS
Result of CTestRecvFromEx(IPV6): PASS
Result of CTestFastHash: PASS
Result of CTestPolling: PASS
Result of CTestAtomicHelpers: PASS
Result of CTestRateLimiter: PASS
You can get a STUN client application for all platforms at https://www.stunprotocol.org (prebuilt EXE clients for Windows and Mac command line apps are up there too!)
Demonstration:
C:\StunServer> stunclient.exe stunserver.stunprotocol.org --mode behavior
Binding test: success
Local address: 192.168.1.7:52707
Mapped address: 101.102.33.44:52707
Behavior test: success
Nat behavior: Endpoint Independent Mapping
C:\StunServer> stunclient.exe stunserver.stunprotocol.org --mode filtering
Binding test: success
Local address: 192.168.1.7:39843
Mapped address: 101.102.33.44:39843
Filtering test: success
Nat filtering: Address Dependent Filtering
Running the two test modes, reveals Endpoint Independent Mapping and Address Dependent Filtering as described in RFC 5780 for classifying NATs.

How to obtain bluetooth port direction with pyserial?

I'm trying to connect to an RN42, module through python. When the RN42 pairs with W10 it creates two virtual COM ports(outgoing and incoming). I need to connect to the outgoing port.
I'm trying to do this automatically. I've tried:
import serial
import serial.tools.list_ports as port_lst
ports = list(port_lst.comports())
bluetooth_ports = []
for p in ports:
if 'Bluetooth' in p.description:
bluetooth_ports += [p.device]
bluetooth_com = serial.Serial(bluetooth_ports[0],115200)
I thought that the first port was usually the outgoing one, but I've paired the module to another computer, and this didn't apply (the second port was the outgoing one). Is there a way to find out the direction of the COM ports?
Thanks!!!
Although this is an antique question, I have been searching for the answer to this for some time myself and since I finally figured it out I wanted others to be able to find the answer. With help from a blog entry at in the hand and its accompanying gist:
The trick is to acquire the hwid using pySerial, then parse the address. The incoming port in a pair has an address of zero and the outgoing port has a nonzero address. Here is some ugly Python code that decodes it:
import serial.tools.list_ports
cp=serial.tools.list_ports.comports()
for p in cp:
if "BTHENUM" in p.hwid:
start_of_address=p.hwid.rfind("&")
end_of_address=p.hwid.rfind("_")
address=p.hwid[start_of_address+1:end_of_address]
if int(address,16)==0:
port_type="incoming"
else:
port_type="outgoing"
print(p.hwid)
print(p.name, address, port_type)
And the output:
BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&0000\7&CC47540&0&000000000000_000000A8
COM4 000000000000 incoming
BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&0002\7&CC47540&0&209BA5420081_C00000000
COM5 209BA5420081 outgoing

RadioTap headers in scapy

I'm trying to send and receive packets with scapy and read the RadioTap Header. The wireless adapter (and driver) is able to handle those headers, but I can't seem to get them.
Whenever I send a normal packet in scapy, is does not contain such a header (thus, sniffing packets and checking one with pkt.haslayer(RadioTap) returns 0, and I am not able to display the header like with pkt[RadioTap].show() ).
If I explicitly construct my packets with a RadioTap header (like in a
pkt = RadioTap() and view it, I can get a RadioTap header, but it is empty. After sending it and receiving it, I can get still nothing.
I read posts like this one. But I don't have the problem that the RadioTap header doesn't get decoded, it's simply not filled with anything.
I'm using scapy 2.3.1, if this makes any difference. Any ideas?
Please make sure that your wireless interface and the driver support monitor mode.
$ iw list
...
Supported interface modes:
* IBSS
* managed
* AP
* AP/VLAN
* monitor <-- here
* P2P-client
* P2P-GO
* P2P-device
And your interface is configured to monitor mode with a specific channel (e.g. ch=6).
$ sudo ip link set wlan0 down
$ sudo iw dev wlan0 set type monitor
$ sudo ip link set wlan0 up
$ sudo iw dev wlan0 set channel 6
It is also good idea to try with tools like wireshark first to see if RadioTap is visible.

How can I get the original destination address of a packet after dnat?

I'm writing a packet filter module at userspace using libnetfilter_queue. But I don't know how to get the original destination address of a packet after it has gone through DNAT filter.
When using socket, I can do it by using SO_ORIGINAL_DST but I don't know how when using libnetfilter_queue.
Thanks.

how i can trace an IP using delphi

i need trace the route of an ip, actually i am using the TIdTraceRoute indy component from the idTraceRoute unit.
IdTraceRoute1:= TIdTraceRoute.Create(Self);
IdTraceRoute1.ResolveHostNames:= True;
IdTraceRoute1.ReceiveTimeout:= 5000;
IdTraceRoute1.OnReply:= TraceRoute;
IdTraceRoute1.Host:= 'www.google.com';
IdTraceRoute1.Trace;
procedure TForm1.TraceRoute(ASender: TComponent;
const AReplyStatus: TReplyStatus);
begin
Memo1.Lines.Add(AReplyStatus.FromIpAddress);
end;
but always return.
0.0.0.0
0.0.0.0
0.0.0.0
0.0.0.0
0.0.0.0
0.0.0.0
exist another way of trace an ip maybe using windows api or using another indy component?
actually i am using delphi-xe and Windows 7.
I just wrote a entry on my blog, wich can help you.
Building a traceroute application with IP geolocation using delphi
Trace is basically based on sending ICMP packets starting with a TTL of 1 and increasing it until reaching the destination. Because each router decrease the TTL, and when it reaches 0 an error is returned to the caller, it can be used to track the "route" packets takes. Note that to work the ICMP protocol must not be stopped by a firewall. ICMP is a protocol that runs atop IP, like TCP does. It doesn't use TCP. You could code a traceroute utility just using ICMP. But does the Windows tracert utility work on your system?

Resources