Re: Lightweight ipset API?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ian,

On Wed, 21 Aug 2019, Ian Pilcher wrote:

> I would like to write a very simple daemon that exists only to add IPv4 
> and IPv6 addresses to an ipset.  (The daemon will run on my firewall and 
> be used to block IPs that are identified by fail2ban on a separate web 
> server.)
> 
> Writing a fail2ban "action" to send an IP address over a socket should 
> be quite straightforward, but I haven't been able to figure out a good 
> way for the daemon (written in C) to add the IP to the set.  Looking at 
> the libipset documentation[1], it seems to require passing in an 
> ipset(8)-style command string.  While the daemon certainly could create 
> such a string and pass it to the library, this seems painfully 
> inelegant.
> 
> The lower level interface seems to be libmnl.  Unfortunately, I can't
> really find anything that I (as a netlink newbie) can follow that tells
> me how I might go about doing this at that level.
> 
> Does anyone have any suggestions on how I might go about figuring this
> out?

There are multiple possibilities at different levels of 
complexity/simplicity, looking at it from different angles :-).

- You could fork ipset in restore mode and push the commands through its
  stdin. Do not forget to issue the "COMMIT" pseudo-command, otherwise
  the commands are aggregated to fit as much as possible into a page and
  then sending the full buffer to the kernel for execution.
- You could use libipset - the parsing is not a big overhead. Admittedly 
  it's not elegant to print the elements internally then parse back the 
  string, but it's the simplest way to use the library.
- You can use the undocumented but public interfaces of libipset in order 
  to skip the parsing. You must load in the set types, init a session and 
  at the end fini. But instead of calling the ipset_parse_foo() 
  functions, what you can do is something like this:

	# get reused data pointer belongig to the session
	struct ipset_data *data = ipset_session_data(session);
	# Assume IPv4...
	uint8_t family = NFPROTO_IPV4;
	# Build the command attributes: setname
	ipset_parse_setname(session, IPSET_SETNAME, "setname");
	# family
	ipset_data_set(data, IPSET_OPT_FAMILY, &family);
	# element
	ipset_data_set(data, IPSET_OPT_IP, &ipaddr_in_netorder);
	# other parts of the element, if any...
	...
	# Tell the system it's an add command
	ipset_cmd_session, IPSET_CMD_ADD, 0);
	# commit
	ipset_commit(session);

    Error checking is left out completely... you should check the source 
    code.
- Also, you could use libmnl directly. In the libmnl source tree there's
  an examples/ subdirectory to start with. Pablo wrote a nice article
  about netlink and libmnl: 
  https://people.netfilter.org/pablo/netlink/netlink-libmnl-manual.pdf
  However, on top of that you must follow the ipset protocol which is not
  documented: the lib/PROTOCOL helps a bit but it's just a bare skeleton.

Best regards,
Jozsef
-
E-mail  : kadlec@xxxxxxxxxxxxxxxxx, kadlecsik.jozsef@xxxxxxxxxxxxx
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences
          H-1525 Budapest 114, POB. 49, Hungary



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux