create iptables rule per process/service
Pergunta
is it possible to use iptables in order to permit traffic initiated by a "process", ie using the process name? I would like for example to allow everything that is initiated by ping command.
Solução
It looks like the owner iptables module is that what you want. First, check if it's available in Your system:
iptables -m owner --help
You can read more here: http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#OWNERMATCH
Outras dicas
-m owner --pid-owner PID
See http://linuxpoison.blogspot.com/2010/11/how-to-limit-network-access-by-user.html and http://linux.die.net/man/8/iptables
Note that you need the ipt_owner module, as --pid-owner is not supported by xt_owner.
For example (this is just an approximation)
#!/bin/bash
$@ &
iptables -m owner --pid-owner %1 -j REJECT
In reality, though, you're better off using --uid-owner and --gid-owner. First, the --pid-owner criterion only matches the exact pid, meaning your program could easily spawn a child process which would not be blocked by this rule. (At least I haven't read otherwise.) Secondly, iptables(8) warns that --pid-owner is broken on SMP systems (which may or may not apply to you, but in either case limits portability). Third, there is a race condition in the script above, because the process is started before it is blocked. (If there is a way to get a process's pid before it starts, then I've never heard about it.)
If there is a way to get a process's pid before it starts, then I've never heard about it.
You could write a wrapper which forks first, then adds the rule and execs the process (assuming the program you're running doesn't fork again), since the PID is not changed by the exec(3) call.
/* NOTE this contains zero error checking */
int main(int argc, char **argv) {
/* Eat argv[0] the name of the wrapper script */
argv++;
argc--;
pid_t my_pid = getpid();
char *iptables_cmd = NULL;
asprintf(&iptables_cmd, "/sbin/iptables -A INPUT -m owner --pid_owner %d -j ACCEPT", my_pid);
system(iptables_cmd);
execv(argv[0], argv);
}