All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Neal P. Murphy" <neal.p.murphy@alum.wpi.edu>
To: Thomas Delrue <thomas.delrue@fundamental-software.net>
Cc: netfilter@vger.kernel.org
Subject: Re: Creating, editing, removing rules from C(++)
Date: Tue, 21 Jul 2015 19:15:35 -0400	[thread overview]
Message-ID: <20150721191535.5002ff3a@playground> (raw)
In-Reply-To: <55AEBC86.5010604@fundamental-software.net>

On Tue, 21 Jul 2015 17:41:26 -0400
Thomas Delrue <thomas.delrue@fundamental-software.net> wrote:

> Hi,
> 
> Is there a way to interact with the firewall rules from a C(++) program?
> What I'm really trying to do is have a program that only allows a
> certain set of CIDRs through the firewall through a particular port.
> However these CIDRs change from time to time and so my application is
> there to update the firewall rules to make sure that the firewall rules
> contain the latest and greatest information that says: "drop everything
> trying to connect to port P EXCEPT for stuff originating from these CIDRs".

It seems in your case that you don't need high performance or high efficiency, so you should be able to use system() to run iptables-restore.

Considering the vagaries of writing a C/C++ program to manipulate netfilter directly (it can be done, but isn't necessarily straightforward and the API can change for various reasons now and again), and considering that your CIDRs only change from time to time, you may find it easier to pipe the changes to iptables-restore.

The idea below is conceptual; it's close but may not be syntactically correct and you may want packet identification to be more solid. It should be enough to point you in the direction of least resistance.

The permanent F/W config might be something like:
----
 ...
-N restrict_1234
-A restrict_1234 -p tcp -m state --state ESTABLISHED \
    -j REJECT --reject-with tcp-reset
-A restrict_1234 \
    -j REJECT --reject-with icmp-admin-prohibited
 ...
-A FORWARD -p tcp -port 1234 -j restrict_1234
-A FORWARD -p udp -port 1234 -j restrict_1234
 ...
----
On firewall setup, the default is to prohibit all conns to port 1234; your daemon will change this when it starts.

When the CIDRs change or when your daemon starts, you could pipe something like the following to iptables-restore:
----
-F restrict_1234
-A restrict_1234 -s CIDR-A -j RETURN
-A restrict_1234 -s CIDR-B -j RETURN
-A restrict_1234 -p tcp -m state --state ESTABLISHED \
    -j REJECT --reject-with tcp-reset
-A restrict_1234 \
    -j REJECT --reject-with icmp-admin-prohibited
----
(I don't remember if iptables-restore reads from STDIN; if not, use a temp intermediate file.) iptables-restore will perform the work atomically. The "-j RETURN" allows your remaining rules to handle the conn; it might not be wise to ACCEPT packets here, but this depends on your firewall design.

You definitely want to reset existing TCP conns; but you can DROP new conn attempts instead of REJECTing them.

One moment, the existing allowed CIDRs are connecting and talking. The next moment, new allowed CIDRs can connect and talk, existing conns from still-allowed CIDRs continue talking, conns from no-longer-allowed CIDRs are immediately disconnected (one side at a time, when the next packet comes in, not one more packet passes through the firewall), and new conn attempts from disallowed CIDRs are rejected. This method works very well when using the time module; one moment the kids are playing their online games and the next moment they are disconnected and cannot reconnect. And it works for TCP and UDP.

You *can* write a C/C++ interface to netfilter. But it's often better, easier, and clearer to use existing utilities. Especially when the task isn't too involved and performance and efficiency aren't all that critical (i.e., "... CIDRs change from time to time..." doesn't seem to require highly efficient code).

N

  parent reply	other threads:[~2015-07-21 23:15 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-21 21:41 Creating, editing, removing rules from C(++) Thomas Delrue
2015-07-21 22:30 ` alvin
     [not found]   ` <55AECB5B.9090302@fundamental-software.net>
2015-07-22 17:01     ` alvin
2015-07-21 23:15 ` Neal P. Murphy [this message]
2015-07-22  0:08   ` Sven-Haegar Koch
2015-07-22  0:31     ` Neal P. Murphy
2015-07-22 13:39   ` Thomas Delrue
2015-07-27 10:25 ` Bastian Bittorf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150721191535.5002ff3a@playground \
    --to=neal.p.murphy@alum.wpi.edu \
    --cc=netfilter@vger.kernel.org \
    --cc=thomas.delrue@fundamental-software.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.