* block network access for certain users/groups @ 2010-07-29 19:09 Elmar Stellnberger 2010-07-29 19:33 ` Lars Nooden 0 siblings, 1 reply; 14+ messages in thread From: Elmar Stellnberger @ 2010-07-29 19:09 UTC (permalink / raw) To: netfilter I need to block network access for certain users/groups, fully: iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP ...drops ping packages in the output chain but lets my user happily connect to localhost:631 or any other http address. In deed the rule above is therefore pretty useless. I need to block ALL incoming and outgoing packages for a certain user/group. At the moment there is only insufficient blocking for outgoing packages available. What will I have to do to implement network access restrictions on a per user/group basis? Logging such packages is already possible. Why is blocking them not? Can anyone help me? Elmar Stellnberger ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-29 19:09 block network access for certain users/groups Elmar Stellnberger @ 2010-07-29 19:33 ` Lars Nooden 2010-07-30 9:00 ` Jan Engelhardt 0 siblings, 1 reply; 14+ messages in thread From: Lars Nooden @ 2010-07-29 19:33 UTC (permalink / raw) To: Elmar Stellnberger; +Cc: netfilter On 7/29/10 10:09 PM, Elmar Stellnberger wrote: > iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP For starters, consider using the REJECT target instead of DROP if for no other reason than that it will make your engineering easier: http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject http://www.chrisbrenton.org/2009/07/why-firewall-reject-rules-are-better-than-firewall-drop-rules/ > What will I have to do to implement network access restrictions on a per > user/group basis? Follow your chains in sequence and make sure that the packets going to or from that group have only one way to go. If the packets are getting through, then there is some chain or rule allowing them through before the packet gets to the --gid-owner rule you have above. /Lars ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-29 19:33 ` Lars Nooden @ 2010-07-30 9:00 ` Jan Engelhardt 2010-07-30 11:34 ` Lars Nooden 0 siblings, 1 reply; 14+ messages in thread From: Jan Engelhardt @ 2010-07-30 9:00 UTC (permalink / raw) To: Lars Nooden; +Cc: Elmar Stellnberger, netfilter, peterb, chris Ref: http://marc.info/?l=netfilter&m=128043201731932&w=2 On Thursday 2010-07-29 21:33, Lars Nooden wrote: > On 7/29/10 10:09 PM, Elmar Stellnberger wrote: >> iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP > > For starters, consider using the REJECT target instead of DROP if for no other > reason than that it will make your engineering easier: > > http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject That page - especially the summary - is leaving out one essential feature Gáspar already mentioned it in another thread; the CHAOS target from Xtables-addons. It is hard to press its behavior into the three rows "application connects to non-existent service" / "naïve network scanning" / "specialist program", but the behavior can be summed up into: 1. Connect: With an x% (tunable) chance, failure is reported promptly to the user/scanner. (This is to elicit point 2.) 2. Scanning many ports will be slow/expensive. (nmap) 3. Syn scans produce nonsensical results. (nmap) > http://www.chrisbrenton.org/2009/07/why-firewall-reject-rules-are-better-than-firewall-drop-rules/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-30 9:00 ` Jan Engelhardt @ 2010-07-30 11:34 ` Lars Nooden 2010-07-30 20:10 ` Elmar Stellnberger 0 siblings, 1 reply; 14+ messages in thread From: Lars Nooden @ 2010-07-30 11:34 UTC (permalink / raw) To: Jan Engelhardt; +Cc: Elmar Stellnberger, netfilter, peterb, chris On 07/30/2010 12:00 PM, Jan Engelhardt wrote: > > Ref: http://marc.info/?l=netfilter&m=128043201731932&w=2 > > On Thursday 2010-07-29 21:33, Lars Nooden wrote: >> On 7/29/10 10:09 PM, Elmar Stellnberger wrote: >>> iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP >> >> For starters, consider using the REJECT target instead of DROP if for no other >> reason than that it will make your engineering easier: >> >> http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject > > That page - especially the summary - is leaving out one essential feature > Gáspar already mentioned it in another thread; the CHAOS target from > Xtables-addons. CHAOS and TARPIT look about the same as DROP in regards to the question of REJECT vs DROP. The same arguments apply about a quick response from the filter or not. http://www.chrisbrenton.org/2009/07/why-firewall-reject-rules-are-better-than-firewall-drop-rules/ http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject /Lars ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-30 11:34 ` Lars Nooden @ 2010-07-30 20:10 ` Elmar Stellnberger 2010-07-31 5:04 ` Richard Horton 0 siblings, 1 reply; 14+ messages in thread From: Elmar Stellnberger @ 2010-07-30 20:10 UTC (permalink / raw) To: Lars Nooden, jengelh, arimus.uk, netfilter Promptly stated we have the following two problems: * The --uid-owner and --gid-owner flags may only be specified in the output chain (as the man page says). However to block all network traffic for a certain user we do also need it in the input chain. Curiously we can log the user who is going to receive a package but we can not select for this. * The --gid-owner iptables-rule is apparently ineffective for http-access (lynx localhost:631). It is the first rule and would be expected to reject any package with the specified gid. Jan Engelhardt & Lars Nooden: Thxs for your advice. Using Reject would for sure be the cleaner solution as Drop only lags for normal app. users and does not help against professional portscans. Nonetheless our primary goal here should be to block all network access for a certain user and only for this user. The idea is to run programs which do not need network access under the specified user id (as apache runs under wwwrun). Richard Horton: I have connected with lynx to cups (localhost:631). Lynx does not have the suid-group id bit set so the group should not change. Lars Nooden & Richard Horton: As you can see my rule is the first to execute (It is on the right place but obviously does not work right): >iptables -L -v Chain OUTPUT (policy ACCEPT 1 packets, 52 bytes) pkts bytes target prot opt in out source destination 8683 506K user_spec all -- any any anywhere anywhere 0 0 ACCEPT all -- any lo anywhere anywhere 8682 506K ACCEPT all -- any any anywhere anywhere state NEW,RELATED,ESTABLISHED 1 52 LOG all -- any any anywhere anywhere limit: avg 3/min burst 5 LOG level warning tcp-options ip-options prefix `SFW2-OUT-ERROR ' Chain reject_func (0 references) pkts bytes target prot opt in out source destination 0 0 REJECT tcp -- any any anywhere anywhere reject-with tcp-reset 0 0 REJECT udp -- any any anywhere anywhere reject-with icmp-port-unreachable 0 0 REJECT all -- any any anywhere anywhere reject-with icmp-proto-unreachable Chain user_spec (1 references) pkts bytes target prot opt in out source destination 0 0 DROP all -- any any anywhere anywhere owner GID match app ... Nonetheless the rule is there and being executed: > ping localhost ping: sendmsg: Operation not permitted ping: sendmsg: Operation not permitted ping: sendmsg: Operation not permitted PING localhost (127.0.0.1) 56(84) bytes of data. --- localhost ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2000ms 2010/7/30 Lars Nooden <lars.curator@gmail.com>: > On 07/30/2010 12:00 PM, Jan Engelhardt wrote: >> >> Ref: http://marc.info/?l=netfilter&m=128043201731932&w=2 >> >> On Thursday 2010-07-29 21:33, Lars Nooden wrote: >>> On 7/29/10 10:09 PM, Elmar Stellnberger wrote: >>>> iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP >>> >>> For starters, consider using the REJECT target instead of DROP if for no other >>> reason than that it will make your engineering easier: >>> >>> http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject >> >> That page - especially the summary - is leaving out one essential feature >> Gáspar already mentioned it in another thread; the CHAOS target from >> Xtables-addons. > > CHAOS and TARPIT look about the same as DROP in regards to the question > of REJECT vs DROP. The same arguments apply about a quick response from > the filter or not. > > http://www.chrisbrenton.org/2009/07/why-firewall-reject-rules-are-better-than-firewall-drop-rules/ > > http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject > > > /Lars > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-30 20:10 ` Elmar Stellnberger @ 2010-07-31 5:04 ` Richard Horton 0 siblings, 0 replies; 14+ messages in thread From: Richard Horton @ 2010-07-31 5:04 UTC (permalink / raw) To: Elmar Stellnberger; +Cc: Lars Nooden, jengelh, netfilter [snipped original] Might be worth turn trace on : iptables -t raw -A OUTPUT -j TRACE See which rules the packets hit; if you want to cut down the amount of traces just add the relevant matches - I tend to trace everything until I know what I'm the packet(s) look like what I expect and then start focusing in. -- Richard Horton Users are like a virus: Each causing a thousand tiny crises until the host finally dies. http://www.pbase.com/arimus - My online photogallery http://www.richardhorton.info ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <AANLkTin8w74SAe67ZPqPE0Q=0fPpZOHnTCnjAT+AduCY@mail.gmail.com>]
* block network access for certain users/groups [not found] <AANLkTin8w74SAe67ZPqPE0Q=0fPpZOHnTCnjAT+AduCY@mail.gmail.com> @ 2010-08-25 11:09 ` Elmar Stellnberger 2010-08-25 11:58 ` Tetsuo Handa 2010-08-25 16:02 ` Hagen Paul Pfeifer 0 siblings, 2 replies; 14+ messages in thread From: Elmar Stellnberger @ 2010-08-25 11:09 UTC (permalink / raw) To: netdev, netfilter-devel Please answer my question: It has not been answered, yet. Thanks for hints like whether to use DROP or REJECT but please answer my question! I wanna be pointed on how to implement a per user package selection. Something similar pretends to be already implemented if you view the man page, but it is only implemented for outgoing packages and it even does not work correctly (blocking outgoing ICMP-ping requests but with lynx you can happily view localhost:631 though the rule is on top and applies to any kind of package (raw, tcp, udp)). We have already checked this thouroughly. I need to block network access for certain users/groups, fully: iptables -A mychain -m owner --gid-owner blockedusergroup -j REJECT ...drops ping packages in the output chain but lets my user happily connect to localhost:631 or any other http address. In deed the rule above is therefore pretty useless. I need to block ALL incoming and outgoing packages for a certain user/group. At the moment there is only insufficient blocking for outgoing packages available. Can you help me? What will I have to do to implement network access restrictions on a per user/group basis? Logging such packages is already possible. Why is blocking them not? ... and yes I have already checked the whole iptables -L -v. The rule is there and would have been supposed to work. Yours, Elmar Stellnberger ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-08-25 11:09 ` Elmar Stellnberger @ 2010-08-25 11:58 ` Tetsuo Handa 2010-08-26 12:28 ` Tetsuo Handa 2010-08-25 16:02 ` Hagen Paul Pfeifer 1 sibling, 1 reply; 14+ messages in thread From: Tetsuo Handa @ 2010-08-25 11:58 UTC (permalink / raw) To: estellnb; +Cc: netdev, netfilter-devel Elmar Stellnberger wrote: > Please answer my question: > It has not been answered, yet. > Thanks for hints like whether to use DROP or REJECT but please answer > my question! > > I wanna be pointed on how to implement a per user package selection. A package sounds something like application. What you want to do is "packet selection" (like iptables) rather than "package selection" (like rpm/dpkg). Please "sed -e 's/package/packet/g'"... > Something similar pretends to be already implemented if you view the > man page, but > it is only implemented for outgoing packages and it even does not work > correctly > (blocking outgoing ICMP-ping requests but with lynx you can happily > view localhost:631 > though the rule is on top and applies to any kind of package (raw, > tcp, udp)). We have > already checked this thouroughly. Regarding incoming packets, it is impossible to perform packet filtering based on uid/gid because the uid/gid who picks up the packet is not known until a user issues accept()/recvmsg(). The socket's owner may change between the moment iptables inspected the packet and the moment a user picks up the packet because it is possible to send the socket's file descriptor via Unix domain socket or call setuid()/setgid(). > I need to block network access for certain users/groups, fully: > > iptables -A mychain -m owner --gid-owner blockedusergroup -j REJECT > > ...drops ping packages in the output chain but lets my user happily > connect to localhost:631 or any other http address. In deed the rule > above is therefore pretty useless. > > I need to block ALL incoming and outgoing packages for a certain user/group. > At the moment there is only insufficient blocking for outgoing > packages available. > > Can you help me? > What will I have to do to implement network access restrictions on a > per user/group basis? The only way that makes possible to block access by blockedusergroup is to insert hooks like http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/net/ipv4/udp.c#L1144 and http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/net/socket.c#L1504 . But such hooks are not acceptable for upstream kernel. Please see http://kerneltrap.org/mailarchive/linux-netdev/2010/7/21/6281491 for discussion on these hooks. > Logging such packages is already possible. Why is blocking them not? > > ... and yes I have already checked the whole iptables -L -v. > The rule is there and would have been supposed to work. > > Yours, > Elmar Stellnberger ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-08-25 11:58 ` Tetsuo Handa @ 2010-08-26 12:28 ` Tetsuo Handa 2010-08-30 11:36 ` Elmar Stellnberger 0 siblings, 1 reply; 14+ messages in thread From: Tetsuo Handa @ 2010-08-26 12:28 UTC (permalink / raw) To: estellnb; +Cc: netdev, netfilter-devel Tetsuo Handa wrote: > Elmar Stellnberger wrote: > > I need to block network access for certain users/groups, fully: Oh, I thought you want to partially block communication by specific user. You want to entirely block communication by specific user? Then, it is easy. You can block all socket syscalls by that user using LSM. I made an example LSM module which can be added as a loadable kernel module ( http://www.youtube.com/watch?v=wG8BTLMu5wo ). You can modify it as you like. You can compile and load below module provided that your kernel config has CONFIG_SECURITY_NETWORK=y . Did this module answer your question? Thanks. ---------------------------------------- /* * Uid-NoSock Linux Security Module * * Author: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> * * This module blocks socket syscalls by specific UID. Use at your own risk. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. */ /* * Place this file (uid_nosock.c) in some directory and create Makefile * containing a line * * obj-m += uid_nosock.o * * and run * * make SUBDIRS=directory_containing_this_file/ modules modules_install * */ #include <linux/security.h> #ifndef CONFIG_SECURITY_NETWORK #error This module depends on CONFIG_SECURITY_NETWORK=y #endif #ifndef CONFIG_SECURITY #error This module depends on CONFIG_SECURITY=y #endif #ifndef CONFIG_KALLSYMS #error This module depends on CONFIG_KALLSYMS=y #endif #ifndef CONFIG_MODULES #error This module depends on CONFIG_MODULES=y #endif #include <linux/module.h> #include <linux/pid_namespace.h> #include <linux/mount.h> #include <linux/fs_struct.h> static struct security_operations original_security_ops; /* UID to block socket syscalls. */ #define UID_NOSOCK_REJECT_UID 500 static bool uid_nosock_deny(void) { return current_uid() == UID_NOSOCK_REJECT_UID; } static int uid_nosock_socket_create(int family, int type, int protocol, int kern) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_create(family, type, protocol, kern); } static int uid_nosock_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_bind(sock, address, addrlen); } static int uid_nosock_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_connect(sock, address, addrlen); } static int uid_nosock_socket_listen(struct socket *sock, int backlog) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_listen(sock, backlog); } static int uid_nosock_socket_accept(struct socket *sock, struct socket *newsock) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_accept(sock, newsock); } static int uid_nosock_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_sendmsg(sock, msg, size); } static int uid_nosock_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_recvmsg(sock, msg, size, flags); } static int uid_nosock_socket_getsockname(struct socket *sock) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_getsockname(sock); } static int uid_nosock_socket_getpeername(struct socket *sock) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_getpeername(sock); } static int uid_nosock_socket_getsockopt(struct socket *sock, int level, int optname) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_getsockopt(sock, level, optname); } static int uid_nosock_socket_setsockopt(struct socket *sock, int level, int optname) { if (uid_nosock_deny()) return -EPERM; return original_security_ops.socket_setsockopt(sock, level, optname); } /* Find symbols from /proc/kallsyms . */ static void *__init uid_nosock_find_symbol(const char *keyline) { struct file *file; char *buf; unsigned long entry = 0; { struct fs_struct *fs = current->fs; struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; struct path old_path; struct path new_path = { mnt, mnt->mnt_root }; spin_lock(&fs->lock); /* was write_lock() till 2.6.35. */ old_path = fs->pwd; fs->pwd = new_path; spin_unlock(&fs->lock); file = filp_open("kallsyms", O_RDONLY, 0); spin_lock(&fs->lock); fs->pwd = old_path; spin_unlock(&fs->lock); } if (IS_ERR(file)) goto out; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (buf) { int len; int offset = 0; while ((len = kernel_read(file, offset, buf, PAGE_SIZE - 1)) > 0) { char *cp; buf[len] = '\0'; cp = strrchr(buf, '\n'); if (!cp) break; *(cp + 1) = '\0'; offset += strlen(buf); cp = strstr(buf, keyline); if (!cp) continue; *cp = '\0'; while (cp > buf && *(cp - 1) != '\n') cp--; entry = simple_strtoul(cp, NULL, 16); break; } kfree(buf); } filp_close(file, NULL); out: return (void *) entry; } /* Never mark this variable as __initdata . */ static struct security_operations *uid_nosock_security_ops; /* Never mark this function as __init . */ static int uid_nosock_addr_calculator(struct file *file) { return uid_nosock_security_ops->file_alloc_security(file); } static int __init uid_nosock_init(void) { struct security_operations **ptr; struct security_operations *ops; int i; const u8 *cp; /* * Guess "struct security_operations *security_ops;". * This trick depends on below assumptions. * * (1) Compiler generates identical code for security_file_alloc() and * uid_nosock_addr_calculator(). * (2) uid_nosock_security_ops is found within 128 bytes from * uid_nosock_addr_calculator, even if additional code (e.g. debug * symbols) is added. * (3) It is safe to read 128 bytes from uid_nosock_addr_calculator. * (4) uid_nosock_security_ops != Byte code except * uid_nosock_security_ops. */ cp = (const u8 *) uid_nosock_addr_calculator; for (i = 0; i < 128; i++) { if (sizeof(uid_nosock_security_ops) == sizeof(u32)) { if (*(u32 *) cp == (u32) &uid_nosock_security_ops) break; } else if (sizeof(uid_nosock_security_ops) == sizeof(u64)) { if (*(u64 *) cp == (u64) &uid_nosock_security_ops) break; } cp++; } if (i == 128) { printk(KERN_ERR "Can't resolve uid_nosock_security_ops structure.\n"); return -EINVAL; } cp = (const u8 *) uid_nosock_find_symbol(" security_file_alloc\n"); if (!cp) { printk(KERN_ERR "Can't resolve security_file_alloc().\n"); return -EINVAL; } /* This should be "struct security_operations *security_ops;". */ ptr = *(struct security_operations ***) (cp + i); if (!ptr) { printk(KERN_ERR "Can't resolve security_ops structure.\n"); return -EINVAL; } ops = *ptr; if (!ops) { printk(KERN_ERR "No security_operations registered.\n"); return -EINVAL; } memmove(&original_security_ops, ops, sizeof(original_security_ops)); smp_mb(); BUG_ON(ops->socket_create == uid_nosock_socket_create || ops->socket_bind == uid_nosock_socket_bind || ops->socket_connect == uid_nosock_socket_connect || ops->socket_listen == uid_nosock_socket_listen || ops->socket_accept == uid_nosock_socket_accept || ops->socket_sendmsg == uid_nosock_socket_sendmsg || ops->socket_recvmsg == uid_nosock_socket_recvmsg || ops->socket_getsockname == uid_nosock_socket_getsockname || ops->socket_getpeername == uid_nosock_socket_getpeername || ops->socket_getsockopt == uid_nosock_socket_getsockopt || ops->socket_setsockopt == uid_nosock_socket_setsockopt); ops->socket_create = uid_nosock_socket_create; ops->socket_bind = uid_nosock_socket_bind; ops->socket_connect = uid_nosock_socket_connect; ops->socket_listen = uid_nosock_socket_listen; ops->socket_accept = uid_nosock_socket_accept; ops->socket_sendmsg = uid_nosock_socket_sendmsg; ops->socket_recvmsg = uid_nosock_socket_recvmsg; ops->socket_getsockname = uid_nosock_socket_getsockname; ops->socket_getpeername = uid_nosock_socket_getpeername; ops->socket_getsockopt = uid_nosock_socket_getsockopt; ops->socket_setsockopt = uid_nosock_socket_setsockopt; printk(KERN_INFO "Uid-Nosock: Blocking socket syscalls by uid=%u.\n", UID_NOSOCK_REJECT_UID); return 0; } module_init(uid_nosock_init); MODULE_LICENSE("GPL"); ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-08-26 12:28 ` Tetsuo Handa @ 2010-08-30 11:36 ` Elmar Stellnberger 2010-08-30 11:55 ` Tetsuo Handa 0 siblings, 1 reply; 14+ messages in thread From: Elmar Stellnberger @ 2010-08-30 11:36 UTC (permalink / raw) To: Tetsuo Handa; +Cc: netdev, netfilter-devel Many Thnaks. This is exactly what I have been looking for! However if I compile the kernel module and try to load it that results in a kernel hang that I can only escape by Alt-PrnScr-S-U-B, no matter whether the module is loaded on boot time or in rl5. I have checked all required kernel options and built it like the following (using openSUSE 11.3): make -C /lib/modules/`uname -r`/build SUBDIRS=~+/ modules || exit $? install -m 644 nwusrblock-module /lib/modules/`uname -r`/kernel/drivers/nwusrblock-module /sbin/depmod -a modprobe nwusrblock-modul 2010/8/26, Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>: > Tetsuo Handa wrote: >> Elmar Stellnberger wrote: >> > I need to block network access for certain users/groups, fully: > Oh, I thought you want to partially block communication by specific user. > > You want to entirely block communication by specific user? Then, it is easy. > You can block all socket syscalls by that user using LSM. > I made an example LSM module which can be added as a loadable kernel module > ( http://www.youtube.com/watch?v=wG8BTLMu5wo ). You can modify it as you > like. > > You can compile and load below module provided that your kernel config has > CONFIG_SECURITY_NETWORK=y . > > Did this module answer your question? > > Thanks. > ---------------------------------------- > /* > * Uid-NoSock Linux Security Module > * > * Author: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> > * > * This module blocks socket syscalls by specific UID. Use at your own risk. > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License version 2, as > * published by the Free Software Foundation. > */ > /* > * Place this file (uid_nosock.c) in some directory and create Makefile > * containing a line > * > * obj-m += uid_nosock.o > * > * and run > * > * make SUBDIRS=directory_containing_this_file/ modules modules_install > * > */ > #include <linux/security.h> > #ifndef CONFIG_SECURITY_NETWORK > #error This module depends on CONFIG_SECURITY_NETWORK=y > #endif > #ifndef CONFIG_SECURITY > #error This module depends on CONFIG_SECURITY=y > #endif > #ifndef CONFIG_KALLSYMS > #error This module depends on CONFIG_KALLSYMS=y > #endif > #ifndef CONFIG_MODULES > #error This module depends on CONFIG_MODULES=y > #endif > #include <linux/module.h> > #include <linux/pid_namespace.h> > #include <linux/mount.h> > #include <linux/fs_struct.h> > static struct security_operations original_security_ops; > > /* UID to block socket syscalls. */ > #define UID_NOSOCK_REJECT_UID 500 > > static bool uid_nosock_deny(void) > { > return current_uid() == UID_NOSOCK_REJECT_UID; > } > > static int uid_nosock_socket_create(int family, int type, int protocol, > int kern) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_create(family, type, protocol, > kern); > } > > static int uid_nosock_socket_bind(struct socket *sock, > struct sockaddr *address, int addrlen) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_bind(sock, address, addrlen); > } > > static int uid_nosock_socket_connect(struct socket *sock, > struct sockaddr *address, int addrlen) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_connect(sock, address, addrlen); > } > > static int uid_nosock_socket_listen(struct socket *sock, int backlog) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_listen(sock, backlog); > } > > static int uid_nosock_socket_accept(struct socket *sock, > struct socket *newsock) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_accept(sock, newsock); > } > > static int uid_nosock_socket_sendmsg(struct socket *sock, struct msghdr > *msg, > int size) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_sendmsg(sock, msg, size); > } > > static int uid_nosock_socket_recvmsg(struct socket *sock, struct msghdr > *msg, > int size, int flags) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_recvmsg(sock, msg, size, flags); > } > > static int uid_nosock_socket_getsockname(struct socket *sock) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_getsockname(sock); > } > > static int uid_nosock_socket_getpeername(struct socket *sock) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_getpeername(sock); > } > > static int uid_nosock_socket_getsockopt(struct socket *sock, int level, > int optname) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_getsockopt(sock, level, optname); > } > > static int uid_nosock_socket_setsockopt(struct socket *sock, int level, > int optname) > { > if (uid_nosock_deny()) > return -EPERM; > return original_security_ops.socket_setsockopt(sock, level, optname); > } > > /* Find symbols from /proc/kallsyms . */ > static void *__init uid_nosock_find_symbol(const char *keyline) > { > struct file *file; > char *buf; > unsigned long entry = 0; > { > struct fs_struct *fs = current->fs; > struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; > struct path old_path; > struct path new_path = { mnt, mnt->mnt_root }; > spin_lock(&fs->lock); /* was write_lock() till 2.6.35. */ > old_path = fs->pwd; > fs->pwd = new_path; > spin_unlock(&fs->lock); > file = filp_open("kallsyms", O_RDONLY, 0); > spin_lock(&fs->lock); > fs->pwd = old_path; > spin_unlock(&fs->lock); > } > if (IS_ERR(file)) > goto out; > buf = kmalloc(PAGE_SIZE, GFP_KERNEL); > if (buf) { > int len; > int offset = 0; > while ((len = kernel_read(file, offset, buf, > PAGE_SIZE - 1)) > 0) { > char *cp; > buf[len] = '\0'; > cp = strrchr(buf, '\n'); > if (!cp) > break; > *(cp + 1) = '\0'; > offset += strlen(buf); > cp = strstr(buf, keyline); > if (!cp) > continue; > *cp = '\0'; > while (cp > buf && *(cp - 1) != '\n') > cp--; > entry = simple_strtoul(cp, NULL, 16); > break; > } > kfree(buf); > } > filp_close(file, NULL); > out: > return (void *) entry; > } > > /* Never mark this variable as __initdata . */ > static struct security_operations *uid_nosock_security_ops; > > /* Never mark this function as __init . */ > static int uid_nosock_addr_calculator(struct file *file) > { > return uid_nosock_security_ops->file_alloc_security(file); > } > > static int __init uid_nosock_init(void) > { > struct security_operations **ptr; > struct security_operations *ops; > int i; > const u8 *cp; > /* > * Guess "struct security_operations *security_ops;". > * This trick depends on below assumptions. > * > * (1) Compiler generates identical code for security_file_alloc() and > * uid_nosock_addr_calculator(). > * (2) uid_nosock_security_ops is found within 128 bytes from > * uid_nosock_addr_calculator, even if additional code (e.g. debug > * symbols) is added. > * (3) It is safe to read 128 bytes from uid_nosock_addr_calculator. > * (4) uid_nosock_security_ops != Byte code except > * uid_nosock_security_ops. > */ > cp = (const u8 *) uid_nosock_addr_calculator; > for (i = 0; i < 128; i++) { > if (sizeof(uid_nosock_security_ops) == sizeof(u32)) { > if (*(u32 *) cp == (u32) &uid_nosock_security_ops) > break; > } else if (sizeof(uid_nosock_security_ops) == sizeof(u64)) { > if (*(u64 *) cp == (u64) &uid_nosock_security_ops) > break; > } > cp++; > } > if (i == 128) { > printk(KERN_ERR > "Can't resolve uid_nosock_security_ops structure.\n"); > return -EINVAL; > } > cp = (const u8 *) uid_nosock_find_symbol(" security_file_alloc\n"); > if (!cp) { > printk(KERN_ERR "Can't resolve security_file_alloc().\n"); > return -EINVAL; > } > /* This should be "struct security_operations *security_ops;". */ > ptr = *(struct security_operations ***) (cp + i); > if (!ptr) { > printk(KERN_ERR "Can't resolve security_ops structure.\n"); > return -EINVAL; > } > ops = *ptr; > if (!ops) { > printk(KERN_ERR "No security_operations registered.\n"); > return -EINVAL; > } > memmove(&original_security_ops, ops, sizeof(original_security_ops)); > smp_mb(); > BUG_ON(ops->socket_create == uid_nosock_socket_create || > ops->socket_bind == uid_nosock_socket_bind || > ops->socket_connect == uid_nosock_socket_connect || > ops->socket_listen == uid_nosock_socket_listen || > ops->socket_accept == uid_nosock_socket_accept || > ops->socket_sendmsg == uid_nosock_socket_sendmsg || > ops->socket_recvmsg == uid_nosock_socket_recvmsg || > ops->socket_getsockname == uid_nosock_socket_getsockname || > ops->socket_getpeername == uid_nosock_socket_getpeername || > ops->socket_getsockopt == uid_nosock_socket_getsockopt || > ops->socket_setsockopt == uid_nosock_socket_setsockopt); > ops->socket_create = uid_nosock_socket_create; > ops->socket_bind = uid_nosock_socket_bind; > ops->socket_connect = uid_nosock_socket_connect; > ops->socket_listen = uid_nosock_socket_listen; > ops->socket_accept = uid_nosock_socket_accept; > ops->socket_sendmsg = uid_nosock_socket_sendmsg; > ops->socket_recvmsg = uid_nosock_socket_recvmsg; > ops->socket_getsockname = uid_nosock_socket_getsockname; > ops->socket_getpeername = uid_nosock_socket_getpeername; > ops->socket_getsockopt = uid_nosock_socket_getsockopt; > ops->socket_setsockopt = uid_nosock_socket_setsockopt; > printk(KERN_INFO "Uid-Nosock: Blocking socket syscalls by uid=%u.\n", > UID_NOSOCK_REJECT_UID); > return 0; > } > > module_init(uid_nosock_init); > MODULE_LICENSE("GPL"); > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-08-30 11:36 ` Elmar Stellnberger @ 2010-08-30 11:55 ` Tetsuo Handa 0 siblings, 0 replies; 14+ messages in thread From: Tetsuo Handa @ 2010-08-30 11:55 UTC (permalink / raw) To: estellnb; +Cc: netdev, netfilter-devel Elmar Stellnberger wrote: > However if I compile the kernel module and try to load it that results > in a kernel hang that I can only escape by Alt-PrnScr-S-U-B, no matter > whether the module is loaded on boot time or in rl5. I have checked > all required kernel options and built it like the following (using > openSUSE 11.3): This module is for 2.6.36 but openSUSE 11.3 uses 2.6.34 . Did you change below spin_lock() to write_lock() and spin_unlock() to write_unlock()? > > { > > struct fs_struct *fs = current->fs; > > struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; > > struct path old_path; > > struct path new_path = { mnt, mnt->mnt_root }; > > spin_lock(&fs->lock); /* was write_lock() till 2.6.35. */ > > old_path = fs->pwd; > > fs->pwd = new_path; > > spin_unlock(&fs->lock); > > file = filp_open("kallsyms", O_RDONLY, 0); > > spin_lock(&fs->lock); > > fs->pwd = old_path; > > spin_unlock(&fs->lock); > > } ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-08-25 11:09 ` Elmar Stellnberger 2010-08-25 11:58 ` Tetsuo Handa @ 2010-08-25 16:02 ` Hagen Paul Pfeifer 1 sibling, 0 replies; 14+ messages in thread From: Hagen Paul Pfeifer @ 2010-08-25 16:02 UTC (permalink / raw) To: Elmar Stellnberger; +Cc: netdev, netfilter-devel * Elmar Stellnberger | 2010-08-25 13:09:34 [+0200]: >What will I have to do to implement network access restrictions on a >per user/group basis? AppArmor, SELinux, ... ? Hagen ^ permalink raw reply [flat|nested] 14+ messages in thread
* block network access for certain users/groups @ 2010-07-29 19:09 Elmar Stellnberger 2010-07-29 19:33 ` Richard Horton 0 siblings, 1 reply; 14+ messages in thread From: Elmar Stellnberger @ 2010-07-29 19:09 UTC (permalink / raw) To: netfilter I need to block network access for certain users/groups, fully: iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP ...drops ping packages in the output chain but lets my user happily connect to localhost:631 or any other http address. In deed the rule above is therefore pretty useless. I need to block ALL incoming and outgoing packages for a certain user/group. At the moment there is only insufficient blocking for outgoing packages available. What will I have to do to implement network access restrictions on a per user/group basis? Logging such packages is already possible. Why is blocking them not? Can anyone help me? Elmar Stellnberger ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: block network access for certain users/groups 2010-07-29 19:09 Elmar Stellnberger @ 2010-07-29 19:33 ` Richard Horton 0 siblings, 0 replies; 14+ messages in thread From: Richard Horton @ 2010-07-29 19:33 UTC (permalink / raw) To: Elmar Stellnberger, netfilter On 29 July 2010 20:09, Elmar Stellnberger <estellnb@gmail.com> wrote: > > > I need to block network access for certain users/groups, fully: > > iptables -A mychain -m owner --gid-owner blockedusergroup -j DROP > Err... I know this is stating the obvious but your output chain does jump to the mychain at some point doesn't it ;) Also some apps remember do not run with the groupid of the person who launched the application - gid-owner matches the *effective* group id of the process. -- Richard Horton Users are like a virus: Each causing a thousand tiny crises until the host finally dies. http://www.pbase.com/arimus - My online photogallery http://www.richardhorton.info ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2010-08-30 11:55 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-29 19:09 block network access for certain users/groups Elmar Stellnberger
2010-07-29 19:33 ` Lars Nooden
2010-07-30 9:00 ` Jan Engelhardt
2010-07-30 11:34 ` Lars Nooden
2010-07-30 20:10 ` Elmar Stellnberger
2010-07-31 5:04 ` Richard Horton
[not found] <AANLkTin8w74SAe67ZPqPE0Q=0fPpZOHnTCnjAT+AduCY@mail.gmail.com>
2010-08-25 11:09 ` Elmar Stellnberger
2010-08-25 11:58 ` Tetsuo Handa
2010-08-26 12:28 ` Tetsuo Handa
2010-08-30 11:36 ` Elmar Stellnberger
2010-08-30 11:55 ` Tetsuo Handa
2010-08-25 16:02 ` Hagen Paul Pfeifer
-- strict thread matches above, loose matches on Subject: below --
2010-07-29 19:09 Elmar Stellnberger
2010-07-29 19:33 ` Richard Horton
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.