how to stop crontrack sessions - c

I have router with linux system based. I have the related SDK to customize the linux system of the router.
When I disable a port forwarding from iptables rules, the running crontack sessions do not go down and keep established.
I want to stop all running crontack sessions when I disable a port forwarding from iptable rules. I mean, only remove the crontack sessions related to the removed rule. So stop all crontack sessions with dest IP (lan IP) = the dest IP of removed rule.
How to do that in kernel space? how to develop a kernel module that go over all crontack session and check the destination IP and remove only the session with a given ipaddress? are there some link for that?
Otherwise are a user space way ( C functions or Linux commands) to stop specific crontack sessions ?

https://www.kernel.org/doc/Documentation/networking/nf_conntrack-sysctl.txt
nf_conntrack_tcp_loose - BOOLEAN
0 - disabled
not 0 - enabled (default)
If it is set to zero, we disable picking up already established
connections.
So the already established connection is detected on-the-fly (without SYN/SYN+ACK/ACK involved) and added back as a new conntrack entry. Since it's a new conntrack entry, the nat table will be traversed again and the DNAT rule applied again. Even if one way doesn't work immediately (if there's no SNAT/MASQUERADE defined in addition to the DNAT rule the http server's outgoing packets might appear on WAN as 192.168.3.17 for a short while and be rejected/ignored by 192.168.33.13), as soon as the other way tries again (ACK retry from 192.168.33.13...) this will match.
Type this:
echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
And try again deleting the conntrack entry with conntrack -D ...
This should hopefully prevent a new conntrack entry to be created and cut the download.
This answer is copied from: https://superuser.com/questions/1258689/conntrack-delete-does-not-stop-runnig-copy-of-big-file

Related

Drop an open TCP connection without sending RST

Looking into nginx: ignore some requests without proper Host header got me thinking that it's not actually possible to close(2) a TCP connection without the OS properly terminating the underlying TCP connection by sending an RST (and/or FIN) to the other end.
One workaround would be to use something like tcpdrop(8), however, as can be seen from usr.sbin/tcpdrop/tcpdrop.c on OpenBSD and FreeBSD, it's implemented through a sysctl-based interface, and may have portability issues outside of BSDs. (In fact, it looks like even the sysctl-based implementation may be different enough between OpenBSD and FreeBSD to require a porting layer -- OpenBSD uses the tcp_ident_mapping structure (which, subsequently, contains two sockaddr_storage elements, plus some other info), whereas FreeBSD, DragonFly and NetBSD use an array of two sockaddr_storage elements directly.) It turns out, that OpenBSD's tcpdrop does appear to send the R packet as per tcpdump(8), and can be confirmed by looking at /sys/netinet/tcp_subr.c :: tcp_drop(), which calls tcp_close() in the end (and tcp_close() is confirmed to send RST elsewhere on SO), so, it appears that it wouldn't even work, either.
If I'm establishing the connection myself through C, is there a way to subsequently drop it without an acknowledgement to the other side, e.g., without initiating RST?
If I'm establishing the connection myself through C, is there a way to subsequently drop it without an acknowledgement to the other side, e.g., without initiating RST?
No. Even if there was, if the peer subseqently sent anything it would be answered by an RST.
NB Normal TCP termination uses a FIN, not an RST.
Cheating an attacker in this way could be a good idea. Of course, in this case you are already reserving server resources for the established connection. In the most basic mode you can use netfilter to drop any TCP outgoing segment with RST or FIN flags set. This rule iptables rule could be an example:
sudo iptables -A OUTPUT -p tcp --tcp-flags FIN,RST SYN -j DROP
Of course, this rule will affect all your TCP connections. I wrote it just to provide a lead of how you can do it. Go to https://www.netfilter.org/ for getting more ideas working on your solution. Basically you should be able to do the same only for the selected connections.
Because of how TCP works, if you're able to implement it, the client (or attacker) will keep the connection open for a long time. To understand the effect it would have in a client read here: TCP, recv function hanging despite KEEPALIVE where I provide results of a test in which the other side doesn't return any TCP segment (not even an ACK). In my configuration, it takes 13 minutes for the socket to enter an error state (that depends on Linux parameters like tcp_retries1 and tcp_retries2).
Just consider a DoS attack will usually imply connections from thousands of different devices and not necessarily many connections from the same device. This is very easy to detect and block in the firewall. So, it's very improbable that you are going to generate resources exhaustion in the client. Also this solution will not work for cases of half-open connection attack.

How to update internal state of nginx' module runtime?

Lets suppose I wish to write a nginx module that blocks clients by IP.
In order to do so, on initialization stage i read a file with IP addresses
that I have to block (black list) and store it in module's context.
Now I wish to update the black list without restarting nginx.
One of the possible solutions, is to add a handler on specific location.
e.g. if uri "/block/1.2.3.4" requested, my handler adds ip address 1.2.3.4 to the black list.
However, nginx runs several workers as separated processes, so only one particular worker will updated.
What is a common pattern to cope such problems?
But nginx does not require a restart (nor any downtime) in order to change the configuration!
See:
http://nginx.org/en/docs/control.html#reconfiguration
In order for nginx to re-read the configuration file, a HUP signal should be sent to the master process. The master process first checks the syntax validity, then tries to apply new configuration, that is, to open log files and new listen sockets. If this fails, it rolls back changes and continues to work with old configuration. If this succeeds, it starts new worker processes, and sends messages to old worker processes requesting them to shut down gracefully. Old worker processes close listen sockets and continue to service old clients. After all clients are serviced, old worker processes are shut down.
As an administrator, it would be my expectation that all modules would, in fact, be controlled in this way, too.
(Of course, if you require a lot of changes to the configuration very often, a different solution might be more appropriate.)
You give an explicit example of blocking access by IP. Are you sure you require a new module in order to accomplish the task? It would seem that a combination of the following standard directives might suffice already:
http://nginx.org/r/deny && http://nginx.org/r/allow
http://nginx.org/r/geo
http://nginx.org/r/map
http://nginx.org/r/if && http://nginx.org/r/return
If you're able to move the black list outside of the module's context, perhaps to a system file, a KV store, or SHM, that would allow each process to talk to a central source blacklist. I believe shmat() and futex will do the job and the overhead will be negligible.

remove one IP from linux route cache programatically

I made a back-end server which redirects users who abuse the main server (via too many invalid webpage requests in a short time) to another port so that the load on the server will be slightly less.
I then in my program via a exec() issue this command to block the IP from regular service:
iptables -t nat -I <tableforport> -p tcp --src <offending ip> -j REDIRECT --to-port <port of my server>
The problem is when I test this using an actual 2-computer setup where one is the client spamming the server (I'm actually holding F5 down for a few minutes to test), The internal port redirection doesn't seem to kick in right away. If I pause from holding F5 down for a few minutes then try again, then the internal redirection works and the blocking message from my server software works.
I feel this is due to linux (which the server runs on) caching remote IP address entries along with its ports along with other instructions causing the new iptables rules (like the one above) to be skipped until the routing cache is flushed for that IP.
In linux, I can easily flush the routing cache for each IP version via:
echo 1 > /proc/sys/net/ipvn/route/flush
where n in ipvn is either a 4 or 6.
The problem with that is if I execute it, then all the good IP's in cache will be flushed which in turn creates a slower experience for all. I only want to create a bad experience to potential hackers.
How do I go about removing only one IP address from the route cache so that when I add a redirection rule to iptables (like above), the redirection takes place right away the moment the client refreshes the page (not several refreshes, seconds or minutes later)?
Once I get an answer, I want to be able to make a C program out of it after which I can probably figure out myself.

UNIX sockets: Is it possible to spoof getsockopt() SO_PEERCRED?

Is there a (compatible) way to spoof (as root) the unix socket (file system sockets) peer credentials which can be obtained by getsockopt(), option SO_PEERCRED?
Background:
I need to connect to a server application (which I cannot modify) which checks the UID of the process which connects to it via SO_PEERCRED. I'd like to spoof the information in order to be able to connect to the application as root, too.
UPDATE
To clarify the question:
I'm searching for a non-invasive way that the server sees a specific peer UID/GID.
Solutions are discouraged which need to alter the kernel (or take the use of kernel modules) or which changes the server process or its loading/linking process in any way (LD_PRELOAD, system call interceptions etc.).
Basically, the solution should work when running on any linux (or unix in general) server without any special requirements. The server process might already be running.
You're on the right lines. A root process has the privileges to spoof things like this, the problem is just that SO_PEERCRED provides no mechanism or API for a process to specify what identity should be to presented to the peer.
Two things you can do:
Temporarily drop root (setreuid(desired,-1)) when you make the connect call. A unix-domain connection is stamped with the credentials of the peer at the time the process called connect (and listen going the other way). SO_PEERCRED does not tell you the credentials of the peer at the current moment. Then you can resume root.
Better, use another API. The message-passing API lets a process pick what identify to present to a peer. Call sendmsg with a struct cmsg that contains the credentials you want to send. The kernel will ignore the credentials specified by an unprivileged user and always make sure the other side sees the actual identity, but a privileged process can pretend to be anyone else. This is a better match for your needs, because dropping and regaining root is a perilous activity and in this case unnecessary. Google for "SCM_CREDENTIALS" (or "man -K" for it on your system) to get code samples.
No. The reason is that the mechanism that provides the UID and GID of the peer is internal to the kernel, and you can't spoof the kernel! The kernel uses the PID of the peer to deduce the effective credentials of the peer. This happens when one side does a connect on the socket. See the call to copy_peercred() from unix_stream_connect() in net/unix/af_unix.c. There isn't any way that the peer can change the data it sends or the socket that will convince the kernel that the peer's PID isn't what it is. This is different from AF_INET sockets where the kernel has no internal knowledge of the peer's process and can only see the data in the IP packet headers that the peer sends.
The only thing that you can do to get this effect is to set the effective UID of the peer process to root or whatever UID/GID you want, and for that you need either root password or sudo privileges.

How do I detect the presence/absence of internet connection on a machine?

I need to detect the presence/absence of internet connection. More precisely, let us suppose that the application is broken up into 2 parts - A and B.
A is responsible for checking whether or not the system is connected to the internet. If it finds that there is no connection, it starts up part B. And as soon as it detects that there is a network connection, it kills B and continues its own work.
What would be the best way to do the A part of the application? Continual pings sounds hideous. There has to be a better way of doing this (preferably in C).
With sufficient privilege you can test the various network interfaces and examine their state. This would tell you if any of the interfaces was connected to a network and operating. However, this won't tell you if the connection is actually usable, i.e., connected to the internet (or your local net if that's all you need). I don't know of anyway to do that short of actually using it.
Using ICMP (ping) can be useful at a low level, but presumably what you need is a connection to an actual endpoint via TCP/IP to do real work. I would say that you should change the design of your application so that B is responsible for indicating when it is unable to continue due to the absence of resources that it relies on -- network or otherwise. A and B should communicate so that A is aware of the situation and is able to either kill B or respond to B terminating itself and thus continuing its work.
A lot of companies have measures in place to prevent outgoing ICMP requests, TCP connections to ports other than 80/443 for example, or even to prevent you from reaching the internet directly by (transparently) proxying your traffic.
Under an internet connection I would understand any way to contact the outside, be it UDP, TCP or ICMP. Depending on what your application needs to contact the internet for, I would suggest to check over the same protocol, as that is the only thing that matters to your app.
If your application uses HTTP to communicate to an external source, try to connect to a few sites you would suspect to not be blacklisted and that have a reliable uptime. Like google.com, microsoft.com, apple.com, and so on...
Edit:
I am unsure what the specifics are, so let me give you an example with a hypothetical situation.
Application A collects data on the system it is running on and forwards it to a Web Service listening on yourserverhost.yourcompany.com:80
Application B would basically take over the job of the Web Service when it is down and log everything so no data is lost.
When all is well, App A will be sending the data to your web service
Once this connection drops, you immediatly launch App B (the obvious remark here would be, why not keep App B running as a failsafe)
App A connects to App B and forwards what it had been buffering
App A continues to try to reestablish the connection to your Web Service and once it is back up will request App B to stop
If the problem you are facing is nothing like this, please provide a more concrete description of what App A and App B are supposed to be doing. I will be more than happy to help.
In your code, you have to check whether the internet connection exists by using a socket to open a connection to a website.
Firstrun: Ask user to input the network parameters, like proxy settings. Save this info.
Next runs: Use these settings to check for the Internet connection. You may simply do a DNS search.
If results are negative, ask user to check settings.
Check whether the cable is connected , if so ping your internet connection to any host as google.com.
ping google.com

Resources