How to set linux kernel not to send RST_ACK, so that I can give SYN_ACK within raw socket - linux

I want to ask a classic question about raw socket programming and linux kernel TCP handling. I've done the research to some same threads like linux raw socket programming question, How to reproduce TCP protocol 3-way handshake with raw sockets correctly?, and TCP ACK spoofing, but still can't get the solution.
I try to make a server which don't listen to any port, but sniff SYN packets from remote hosts. After the server do some calculation, it will send back a SYN_ACK packet to corresponding SYN packet, so that I can create TCP Connection manually, without including kernel's operation. I've create raw socket and send the SYN_ACK over it, but the packet cannot get through to the remote host. When I tcpdump on the server (Ubuntu Server 10.04) and wireshark on client (windows 7), the server returns RST_ACK instead of my SYN_ACK packet. After doing some research, I got information that we cannot preempt kernel's TCP handling.
Is there still any other ways to hack or set the kernel not to responds RST_ACK to those packets?
I've added a firewall to local ip of server to tell the kernel that maybe there's something behind the firewall which is waiting for the packet, but still no luck

Did you try to drop RST using iptables?
iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
should do the job for you.

I recommend using ip tables, but since you ask about hacking the kernel as well, here is an explanation of how you could do that (I'm using kernel 4.1.20 as reference):
When a packet is received (a sk_buff), the IP protocol handler will send it to the networking protocol registered:
static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb)
{
...
ipprot = rcu_dereference(inet_protos[protocol]);
if (ipprot) {
...
ret = ipprot->handler(skb);
Assuming the protocol is TCP, the handler is tcp_v4_rcv:
static const struct net_protocol tcp_protocol = {
.early_demux = tcp_v4_early_demux,
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
.no_policy = 1,
.netns_ok = 1,
.icmp_strict_tag_validation = 1,
};
So tcp_v4_cv is called. It will try to find the socket for the skb received, and if it doesn't, it will send reset:
int tcp_v4_rcv(struct sk_buff *skb)
{
sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
if (!sk)
goto no_tcp_socket;
no_tcp_socket:
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard_it;
tcp_v4_send_reset(NULL, skb);
...
There are many different ways you can hack this. You could go to the xfrm4_policy_check function and hack/change the policy for AF_INET. Or you can just simply comment out the line that calls xfrm4_policy_check, so that the code will always go to discard_it, or you can just comment out the line that calls tcp_v4_send_reset (which will have more consequences, though).
Hope this helps.

Related

How to create a kernel module that can intercept all packets coming to/from a network interface

I have 2 port NIC on my system - eth0 and eth1 as seen by Linux.
I want to intercept all packets coming in/to eth0, send them out through eth1 to an external device connected to the same switch as eth1 is. So I need to slap on an additional header to make it reach the correct external device.
I know that there is a concept of network taps that both the transmit and receive code in the kernel send to, but how do I create one? Also I want to capture not just IP, but all ethernet packets, I know NETFILTER_HOOK would have helped me get me IPv4 packets.
The can be readily implemented with a rx_handler:
static rx_handler_result_t handle_frame(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct net_device *whereto_dev;
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
return RX_HANDLER_CONSUMED;
*pskb = skb;
whereto_dev = rcu_dereference(skb->dev->rx_handler_data);
skb->dev = whereto_dev;
return RX_HANDLER_ANOTHER; /* Do another round in receive path */
}
They are registered via netdev_rx_handler_register(slave_dev, handle_frame, whereto). See the bonding or my uman driver for example usage.
dev_add_pack would work too, but it seems, apart from af_packet.c, all all-packet-catching users of dev_add_pack have been migrated to use rx_handlers, e.g. https://patchwork.ozlabs.org/patch/367236/. The patch's discussion suggests this might be more effecient.

Linux raw datalink layer socket only returns partial packet (96 bytes)

In my application, I am receiving packets at the data link layer using a raw socket (type PF_PACKET, SOCK_RAW). What I am finding is that I only get the first 96 bytes of any packet. I'm assuming there is some option somewhere that is preventing me from receiving the entire packet, but what?
Here is a snipped from my code:
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
int nBytesRead = read(sock, (char *) buf, 1500);
int nFlags = fcntl(m_sock, F_GETFL, 0); // make it non-blocking
fcntl(sock, F_SETFL, nFlags | O_NONBLOCK);
nBytesRead is never more than 96, even though my network sniffer shows longer packets. This is uClinux if that makes a difference.
I found someone else with the same problem at http://www.network-builders.com/raw-socket-captures-only-first-96-bytes-packet-t57283.html but no answers there.
Solved it! What I failed to mention in my original post was that I was attaching a filter to the raw socket so it would only receive traffic on certain TCP/IP ports. This filter code was created with TCPDUMP, which apprently limits capture to 96 bytes by default. I had to add the -s0 option to my TCPDUMP command line to tell it to capture everything:
tcpdump -dd -s0 "ip and tcp and dst port 60001".
With that change, it now gives me the full packet. Thanks to this blog post for the clue.
Hope this helps someone else in the future.

How to generate socket errors on network bridge

I am trying to create a test environment to test the handling of network errors between a client and a server. I cannot change the software on either. The two devices will be connected across a Linux bridge and I will be using various bandwidth shaping tools to restrict bandwidth or block traffic altogether to simulate various error conditions.
Another thing I need to do, which I have no idea yet how to achieve, is to generate socket errors on existing connections. I'd prefer to use an existing Linux tool/utility, but may be able to write my own with enough guidance. I'm pretty familiar with basic networking, TCP and UDP and all that, but not with bridging.
Can anyone suggest a way I can generate socket errors, e.g. by triggering unexpected FIN packets, to both ends of a socket that connects across a bridge?
Thanks in advance.
You can generate with scapy FIN or RST packets easily sniffing in the bridge (usually br0) and crafting proper RST or FIN packets.
Here goes an example, where a RST is sent in the same direction of a packet with data.
#!/usr/bin/python
from scapy.all import *
import random
def sendRST(p):
flags = p.sprintf("%TCP.flags%")
if flags != "S":
ip = p[IP] # Received IP Packet
tcp = p[TCP] # Received TCP Segment
if ip.len <= 40:
return
i = IP() # Outgoing IP Packet
i.dst = ip.dst
i.src = ip.src
t = TCP() # Outgoing TCP Segment
t.flags = "R"
t.dport = tcp.dport
t.sport = tcp.sport
t.seq = tcp.seq
new_ack = tcp.seq + 1
print "RST sent to ",i.dst,":",t.dport
send(i/t)
while (1):
PKT = sniff (iface = "br0", filter = "tcp and src host x.x.x.x", count=1, prn=sendRST)
exit()
Check the options of sniff, wich is extremely powerfull :)
Hope to help you.

Linux app sends UDP without socket

fellow coders.
I'm monitoring my outgoing traffic using libnetfilter_queue module and an iptables rule
ipatbles -I OUTPUT 1 -p all -j NFQUEUE --queue-num 11220
A certain app, called Jitsi (which runs on Java) is exhibiting such a strange behaviour a haven't encountered before:
My monitoring program which process NFQUEUE packets clearly shows that UDP packets are being sent out,
yet when I look into:
"/proc/net/udp" and "/proc/net/udp6" they are empty, moreover "/proc/net/protocols" has a column "sockets" for UDP and it is 0.
But the UDP packets keep getting sent.
Then after a minute or so, "/proc/net/udp" and "/proc/net/protocols" begin to show the correct information about UDP packets.
And again after a while there is no information in them while the UDP packets are being sent.
My only conclusion is that somehow it is possible for an application to send UDP packets without creating a socket and/or it is possible create a socket, then delete it (so that kernel thinks there are none) and still use some obscure method to send packets outside.
Could somebody with ideas about such behaviour land a hand, please?
Two ideas:
Try running the app through strace and take a look at that output.
You could also try to run it through systemtap with a filter for the socket operations.
From that link:
probe kernel.function("*#net/socket.c").call {
printf ("%s -> %s\n", thread_indent(1), probefunc())
}
probe kernel.function("*#net/socket.c").return {
printf ("%s <- %s\n", thread_indent(-1), probefunc())
}
Thank you Paul Rubel for giving me a hint in the right direction. strace showed that Java app was using IPv6 sockets. I had a closer look at /proc/net/udp6 and there those sockets were. I probably had too cursory a view the first time around chiefly because I didn't even expect to find them there. This is the first time I stumbled upon IPv4 packets over IPv6 sockets. But that is what Java does.
Cheers.

linux raw socket programming question

I am trying to create a raw socket which send and receive message with ip/tcp header under linux.
I can successfully binds to a port and receive tcp message(ie:syn)
However, the message seems to be handled by the os, but not mine. I am just a reader of it(like wireshark).
My raw socket binds to port 8888, and then i try to telnet to that port .
In wireshark, it shows that the port 8888 reply a "rst ack" when it receive the "syn" request. In my program, it shows that it receive a new message and it doesnot reply with any message.
Any way to actually binds to that port?(prevent os handle it)
Here is part of my code, i try to cut those error checking for easy reading
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
int tmp = 1;
const int *val = &tmp;
setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8888);
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
//call recv in loop
When your kernel receives a SYN/ACK from the remote host, it finds no record of it having sent a SYN to that IP:PORT combination (which was sent from your raw socket) which is why it assumes that there has been an error and sends a RST to the remote host. This problem can be solved by setting up an IP filter that blocks all TCP traffic on that port (Check the iptables manpage for this). That way you don't have to program in kernel space nor will there be any affect on already existing kernel TCP modules.
man 7 raw says:
Raw sockets may tap all IP protocols in Linux, even protocols like ICMP or TCP which have a protocol module in the kernel. In this case the packets are passed to both the kernel module and the raw socket(s).
I take this to mean that you can't "do TCP" on a raw socket without interference from the kernel unless your kernel lacks TCP support -- which, of course, isn't something you want. What raw sockets are good for is implementing other IP protocols that the kernel doesn't handle, or for special applications like sending crafted ICMP packets.
To access raw headers you dont bind a raw socket to a port. Thats not done.
Simply write a sniffer , to "PICK UP" all incoming packets and find out "YOUR" ones. That will also give you access to all of the packets content etc.
This is how you do it :
int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
while(true)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
In the ProcessPacket function analyse the packet and see if they belong to your application.
Edit:
In case you intend to program raw sockets, check this.
It has a few examples of how to send and receive raw packets.
In case you want to use SOCK_STREAM and SOCK_SEQPACKET connection-oriented type sockets:
You need to tell it to listen after binding to a given address:port.
int connectionQueue = 10;
if ( -1 == listen(sockfd, connectionQueue) )
{
// Error occurred
}
Afterwards, you will need to verify the descriptor for incoming connections using select, and accept an incoming connection on either the server socket (which will lead to not accepting new connections), or a dedicated client socket.

Resources