2

How can iptables run a command or script on a new connection attempt?

Requirement:

External packet to (server interface eth0) ---> (Server interface eth0) input table detects new packet received on port 22 --> iptables runs a command or script

Me thinks, so far, for example:

iptables -A INPUT -i eth0 -p tcp --dport 22 -s xxx.xxx.xxx.xxx/24 -d xxx.xxx.xxx.xxx/32 -m state --state NEW (then do something here like run a script or command (but how?) ) -j ACCEPT

Further reading from a similar question with two answers:

Run shell script based on IPTABLES port access attempt

user40524
  • 294
  • 1
    It would appear that you have accidentally created two accounts.  You should use the contact form and select “I need to merge user profiles” to have your accounts merged.  In order to merge them, you will need to provide links to the two accounts.  For your information, these are http://unix.stackexchange.com/users/138054/yellow-bellied-brave and http://unix.stackexchange.com/users/138169/yellowbelliedbrave.  You’ll then be able to [edit], comment on and accept answers to this question — or delete it, if that’s what you really want to do. – G-Man Says 'Reinstate Monica' Oct 12 '15 at 18:14

1 Answers1

6

I don't think iptables has this capability. I think your best bet is to:

  1. set up special logging for iptables (-j LOG --log-prefix "NEW_CONN_ATTEMPT ")
  2. monitor log with tail
  3. run your command when a match is found

For 2 and 3, a oneliner such as this would do the trick:

tail -f /var/log/firewall.log | awk '/NEW_CONN_ATTEMPT/ {system("/usr/local/bin/script.sh")}'
A.P.
  • 1,416
  • 9
  • 11
  • 2
    Also, fail2ban could be setup for this. – earthmeLon Oct 11 '15 at 20:23
  • Okay, this looks doable, so I will give it a try, but how would we detect if a connection for the command which is executed is already running, and if so, then do not run again. For example, two clients connect to the same server, for at least one client, it would be a new connection attempt, and not for the other. So the command/script on connection attempt would not be required to be executed if already running from the very first connection attempt from the first client. – Yellow Bellied Brave Oct 11 '15 at 21:12
  • @YellowBelliedBrave If you only need to run your script for new connections, make sure the connection state is being logged as well, then modify the awk regex to additionally match the connection state info in the log file. – A.P. Oct 11 '15 at 21:19
  • @earthmeLon can you elaborate on fail2ban..... – Yellow Bellied Brave Oct 11 '15 at 21:21
  • @A.P. can you provide more details as well... – Yellow Bellied Brave Oct 11 '15 at 21:21
  • fail2ban is a program designed to watch your iptables logs and act in different ways. By default, it will block IPs who have made a significant amount of failed ssh logins within a certain timeframe. fail2ban has many other recipies, as well as a nice way of creating customizable rules with plenty of documentation. Not entirely sure it fits this use case 100%, but it seems on-topic. – earthmeLon Oct 11 '15 at 21:23
  • @earthmeLon, lol...yes, i'm quite familiar with fail2ban, but not in this context, but I will read its documentation to find out how it can be applied to this problem as a solution, including how to detect an already existing connection and not run the given command/script if already running. – Yellow Bellied Brave Oct 11 '15 at 21:25
  • @YellowBelliedBrave your iptables rule already matches -m state --state NEW. If you need to run a script only for new connections, simply add an identical rule, but replace -j ACCEPT with -j LOG --log-prefix "NEW_CONN_ATTEMPT ". Then, when you monitor the logs for NEW_CONN_ATTEMPT, the oneliner will only run your script for new connections. Is this what you need? – A.P. Oct 11 '15 at 21:28
  • @A.P. yes, however, when another client connects to the server, for that cleint, it is a new connection, but i think perhaps this is more solvable at the script end with some if else do – Yellow Bellied Brave Oct 11 '15 at 21:30
  • @A.P. or perhaps iptables itself can choose not to log if already established as even if a new client connects, it is not considered to be an established connection by iptables.

    iptables () ! -m state --state ESTABLISHED (using the ! char as NOT)

    – Yellow Bellied Brave Oct 11 '15 at 21:39
  • @YellowBelliedBrave Yes, that's what I suggested earlier: make iptables only log new connections (not established or related) and prefix them with NEW_CONN_ATTEMPT or similar. That way you'll also run your script for new connections, not related or established. That's what your question says: "Have iptables run command/script on new connection attempt". – A.P. Oct 11 '15 at 21:46
  • @A.P. okay, I'm going to give it a try, will comment with results after experimenting.

    iptables -A INPUT -i eth0 -p tcp --dport 22 -s xxx.xxx.xxx.xxx/24 -d xxx.xxx.xxx.xxx/32 -m state --state NEW ! -m state --state ESTABLISHED -j LOG --log-prefix "NEW_CONN_ATTEMPT ")

    – Yellow Bellied Brave Oct 11 '15 at 21:52
  • @A.P. no dice. also, previous comment with string requires correction as such: iptables -A INPUT -i eth0 -p tcp --dport 22 -s xxx.xxx.xxx.xxx/24 -d xxx.xxx.xxx.xxx/32 -m state --state NEW -m state ! --state ESTABLISHED -j LOG --log-prefix "NEW_CONN_ATTEMPT" (moved ! char to correct place, deleted bracket)

    it was also found that a single client can open multiple new connections which cannot be differentiated from an entirely different client also opening multiple new connections. the result would be logging each and every 'new' connection even if that new connection is from the same client.

    – Yellow Bellied Brave Oct 12 '15 at 00:58
  • @YellowBelliedBrave what exactly are you referring to by "no dice"? What doesn't work? Do you mean you now need to differentiate between unique clients, not just new connections? – A.P. Oct 12 '15 at 10:53