I'm trying to implement a feature where depending on the path of the HTTP request I can forward the request to a different port.
For example if the request GET /foo, I would like to forward it to port 81, and if it's /bar I would like to forward it to port 82. And if it's something else, I'd like to continue to forward it to port 80 as it was incoming.
Is there an example eBPF program like this?
I'm trying to figure out how I will determine what HTTP request is because eBPF will apply at packet level
I am not aware of such example at this time. I know that the Cilium project uses BPF to create filters at the HTTP API level, but they generate the BPF programs on the fly and I do not believe the repo has pre-compiled examples.
As you mentioned, eBPF programs process the whole packet, including L2/L3/L4 headers. So in order to determine the HTTP request you have, you would have to do something like this:
Get the ethertype
If ethertype is not IPv4 or IPv6, exit (e.g. pass or drop the packet), otherwise, carry on
Get IP protocol type
If IP protocol type is not TCP, exit
Get TCP destination port
If this port is not 80, exit
Get first 4 bytes of app layer
Are those bytes GET␣? If not, exit.
If yes, try matching the following bytes with your paths /foo and /bar
If it matches, change destination port to 81 or 82 accordingly
For the first steps at least (processing of Ethernet, IP, TCP) you have available examples on the web. From parse_simple.c in kernel samples to more complex ones such as this L4 load balancer on Netronome's samples repository.
Related
I connect to a web server supported by an embedded system with Internet Explorer 9. Windows 7 is on the client side.
The web page have many tabs and I browse across until the problem occurs. It takes about one minute to happen.
The embedded system freezes so it not possible to browse and it does not respond to ping. After a moment the embedded system will recover because it is designed to reboot. I joined a Wireshark trace in which you can see 92 connections (use the filter "tcp.stream eq 0" with values [0,91]) and you will see. I have the source code so I know that the embedded system does not support more than 37 simultaneous connections. Is the cause an exhaustion of the resources?
But I have a more basic question and I really more appreciate an answer to it. The web server is at 172.21.1.12 port 80 and the client is at
172.21.9.70 and variable port numbers (see the trace). Because the IP and port on the server side do not change, how many sockets are in use on the server side? The question is important because the more sockets are opened, the more probably there is an exhaustion of the resources.
If the answer is only 1 socket then I must conclude there is no lack of resources because it can support 37.
I also suggest you use the filter ip.addr == 172.21.1.12 in Wireshark.
I thought I could upload the wireshark file. I dont know how to share it with you. Help please?
Dropbox?
Under the caveat that you haven't specified your embedded system, most TCP stacks will create a new socket for each new connection, and the mapping from socket to connection is 1-1.
When a packet arrives to the network stack, it has to associate that packet to the right socket. Usually, this is accomplished by employing a map from the TCP 4-tuple to the socket, where the 4-tuple consists of [local-ip, local-port, remote-ip, remote-port].
A server makes its service available by listening on a fixed local port that is known to clients wanting to use the service. As you understand, this is usually port 80 for a web server, and the software interface for most TCP implementations dedicate a socket for the purpose of allowing the API to perform operations on the network parameters for this service. However, the socket is not fully connected (the last two parts of the 4-tuple are set to a special "not specified" value, usually all bits 0). When a new connection is accepted, a new socket is created where the 4-tuple consists of the local information of the listening socket and the remote information taken from the source address and port of the SYN packet that initiated the TCP connection.
The limit on the number of connections a server can support is based on how the operating system is configured (you say yours limits it to 37). Using the 4-tuple, a single service (that is a fixed local-ip and local-port) will have an absolute limit of (2ADDR_BITS - RESERVED_ADDRS) × (216 - RESERVED_PORTS). For IPv4, the number of bits is 32, while for IPv6, the number of bits is 128.
When creating a connection, the client will specify the destination address and port (which fills out the remote information for the 4-tuple), but usually leave the source information unspecified. The TCP stack will choose an appropriate source address based on routing, and select an available source port (which will become the local information to complete the 4-tuple). In theory, any source port that is not being used by the selected local interface to communicate to the same remote service can be used as the local port. Most stacks will dedicate a set of the higher numbered ports for this purpose (referred to as the ephemeral port range).
Problem statement:
Suppose a parent server is hosted on a machine IP: 1.1.1.1 and that server some time communicates with three different servers say A (1.1.1.2), B (1.1.1.3), C (1.1.1.4). Those servers may be database servers or any other servers.
Now from your browser you can send a http request to 1.1.1.1/somePage.htm, as a result some TCP packet will go to the server 1.1.1.1, and 1.1.1.1 can send and receive some TCP packets from A,B,C as well.
Aim is to get the information of all TCP packets from the browser machine, without installing any agent software in any servers.
One solution is we can write a code at the 1.1.1.1 server machine that will filter all the TCP packets with respect to respective IPs. But I don’t want that solution.
Is there any way to solve this issue? Is it possible to introduce new protocol for this? But server codes can’t be modified.
Does "any agent software" includes something like Wireshark? Usually the way to look at all datagrams received is by using a sniffer like Wireshark or you can use tcpdump in Linux servers.
You can also use Netfilter to handle received packets in the server an take certain actions on them.
If all the above is included in what you don't want to do the only alternative I see is to add another server in the middle between the browser and the web server (or between the server and a load balancer if you have a load balancer) that acts only as a router or bridge. In that machine you can inspect and filter TCP segments with all the available tools.
I have 2 sip clients on the same computer.
Both of them is registering to a server that is running on port 5060.
For the first client the UDP is on port 5060 and for the other is 5061. When I come from one client to another, after the ringing part i receive the error:
only one usage of each socket address is normally permited.
Got any ideas why I got this error?
Your server and client are both trying to use port 5060, hence the error message. Change the first client to use 5062 or something else.
Also, 5061 is normally used for secured SIP (normal listening port + 1 in the proxy/server). Do not use it for the second client.
It means you're clients are both trying to claim the same socket for the communication channel, or the server is trying to reclaim the socket given to client A, to reuse it for client B.
The software handeling the socket, should be smart enough to rely on the OS to assign port numbers instead of hardcoding the port numbers in the code, this is a 100% guarantee for socket issues.
is it possible to send an echo-request to a host set behind nat
after. all the echo-request doesn't hold a port for the destination host so if there are several hosts using the same external ip address how will the nat be able to forward the echo-request to a specific host
Most modern NAT/packet filtering implementations are stateful. That means they have a wider concept of the word connection than the older stateless variants. That allows them to handle more complex protocols that use additional connections (e.g. FTP), as well as connection-less protocols like ICMP.
In the case of ICMP packets, echo requests contain an ID field that is preserved in the reply. While its 16 bits are somewhat restrictive, it allows in conjuction with the source IP address from the IP header to have a reasonably high confidence on which echo request each reply corresponds to.
EDIT:
As for targeting specific hosts behind a NAT implementation, that is not generally possible. You might be able to:
Redirect all ICMP traffic to one internal host to monitor that one host only.
Use the "pad" data bytes of the echo request packet to provide some kind of host identifier. For example, the -p option of ping on some Linux systems allows setting that field. This is by no means standard, though.
In general, NAT is supposed to hide the hosts behind it from the world, with the exception of any forwarded IP connections.
I have installed a streaming server "Lighttpd" (light-tpd) which runs on port 81.
I have a C program that listens to http requests on port 80 using a server socket created by socket api.
I want that as soon as I get a request on the port 80 from a client I forward that to the streaming server and the remaining conversation takes place b/w the Streaming Server and client & they bypass my C program completely.
The problem is client would be expecting msgs from socket at port 80 (i.e from the socket of my C program) since it had sent request to port 80 only rather than from the Streaming server which gives service on port 81.
can anyone help me out on this issue of bypassing the socket on port 80 for replying to the client.
Solution I think: my program can be a middle man...It will forward the request to port 81 of streaming server and when it get replies from there it forwards them to the client...but bypassing would be efficient and I don't know how to do that. Please help me out.
Thanks in advance
Why put your C program in front? Lighttpd is designed to act as a frontend proxy (among other uses), so you can put lighttpd in front and use its mod_proxy_core to pass requests to your C program. You can use X-Rewrite and/or X-Sendfile to pass requests back to Lighttpd after doing some processing inside your application.
I have recently implemented a similar technique where a single program accepts a TCP connection and then 'passes' that connection to another component and plays no further part in the socket conversation. It uses the technique of passing the file descriptor of the accepted socket over a UNIX socket to the server component which effectively does an inter-process dup() of the fd.
See here and here.
This works for me as I have control of both ends of the UNIX socket on the server-side, but to work for you, you'd need:
A UNIX socket between your dispatching component and server components.
Full control of the server component.
You might need to hack away at the lighttpd source code...
Sorry, not really an proper answer...