User based network restriction

Ubuntu Version

Ubuntu 22.04 LTS

Desktop Environment (if applicable)

GNOME

Problem Description

How do i restrict network access for a particular user ?. This system will be used by multiple users simultaneously.

Specific user should only access specified servers or network and rest should be blocked.

I’m confused by what can be used to achieve this, nf tables, iptables, ufw or something else.

Thanks.

As long as you can list IP(v6) addresses this can be done with either iptables or nftables. For iptables it is --uid-owner or --gid-owner extension (see man iptables-extensions). For nftables it is meta skuid/skgid match.

ufw is just a frontend to iptables, so you would need to add raw iptables rules anyway.

You need to be more precise what does it mean. The above applies to the process UID. If user can su/sudo to another user, those packets will originate from the target user and not subject to the restrictions of the source user.

1 Like

For low-level which cannot be bypassed, the iptables approach is the one … but that ONLY applies to outgoing!

#
# For that specified user, this will allow any interractions with Apps that require localhost routing
#
sudo iptables -A OUTPUT -o lo -m owner --uid-owner username -j ACCEPT

#
# This will block all other outgoing traffic for that specified user
#
sudo iptables -A OUTPUT -m owner --uid-owner username -j DROP

For incoming, you have to define a rule for every service/host that you need to block! Since that is a near impossible task, you need to take two approaches:

  • [a] dis-allowing access to specified Apps by the specified user, and

  • [b] scan for, and detect, ports that the user is listening to and kill the associated processes.


For tactic [b]:
(need to build a boot-time script to start scanning and killing associated PIDs)

#
# To identify listening activity (with associated PID)
#
sudo ss -tunlp

That will report a list looking like this:

Netid  State   Recv-Q  Send-Q   Local Address:Port      Peer Address:Port  Process  
tcp    LISTEN  0       128          127.0.0.1:631            0.0.0.0:*      users:(("cupsd",pid=1623,fd=7))


For tactic [a]:

You need to set that user in his own group, and dissallow access to specified Apps, by making those Apps only executable by allowed groups.

Depending on how fine a control you want,

  • put every accessible App in a group by itself, then

  • add privileged users to that App group on an App-by-App basis.



In other words, if that User is not part of the group that owns and allows usage of a specified App, that User cannot use it, or even see it depending on the way the “other” privileges are set!

To express the problem in a more general security-oriented language, you basically need to fully implement what is referred to as Role-Based Access Control (RBAC). Normal Linux security offers this, essentially as a built-in, as long as the Apps and Users have been properly defined and assigned as outlined above.

IF … you need to go into such a “deep” and “disciplined” approach to limiting access for a potential interloper to who you are giving login access, there are many books out there that discuss the issues, strategies and methods of implementation.

Some reference sites:


Hope those help!

2 Likes

In nftables “-u, --guid Translate numeric UID/GID to names as defined by /etc/passwd and /etc/group” option is there. Is this same as “meta skuid/skgid” you have mentioned ?.

You need to be more precise what does it mean

e.g. ubuntu desktop is used as bastion host for external vendors. VendorAA require only access to their machines they are maintaining, and respective systems for VendorBB. each vendor have local user accounts that are not part of sudoers group.

Hope this clarifies.

Thanks,

I want to allow outgoing traffic to specific ip or networks and block all other traffic for the specific user.

Would something like the following work ?. or is it implicit DROP for all traffic from specified user ?.

iptables -A OUTPUT -m owner --uid-owner username -d 1.1.1.1 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner username -d 192.168.255.0/24 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner username -j DROP

Should we specify what tables to use ? filter/mangle or just the above is sufficient ?.

That is on the right track, but with a GNOME desktop system, your snippet will accidentally break local desktop IPC (DBus, audio, Wayland/X11) and DNS resolution.

Answers to your questions and the missing pieces:

  1. Which table? - You don’t need to specify -t filter or -t mangle. Default is filter, which is exactly where OUTPUT rules belong.

  2. Loopback (lo) is mandatory- Never block -o lo for that user, or their desktop session and local background services will hang on login.

  3. DNS: If the vendor needs to resolve any server hostnames, port 53 (UDP/TCP) must be allowed.

  4. Use REJECT instead of DROP: With DROP, client applications hang for 60+ seconds waiting for a timeout. REJECT immediately returns “Connection refused”, which is cleaner for end users.

Copy-paste for your bastion setup :

# Allow local desktop IPC (DBus, Wayland, Pipewire)
iptables -A OUTPUT -m owner --uid-owner username -o lo -j ACCEPT

# Allow established connections (replies to allowed traffic)
iptables -A OUTPUT -m owner --uid-owner username -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow DNS resolution
iptables -A OUTPUT -m owner --uid-owner username -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner username -p tcp --dport 53 -j ACCEPT

# Allow your target IPs / subnets
iptables -A OUTPUT -m owner --uid-owner username -d 1.1.1.1 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner username -d 192.168.255.0/24 -j ACCEPT

# Reject everything else immediately (avoids app hangs)
iptables -A OUTPUT -m owner --uid-owner username -j REJECT --reject-with icmp-port-unreachable
1 Like

No, it is not the same. The -u option applies to the nft output. The rules themselves only work with numerical UID/GID.

The only thing that I would add to what Viktor (@steelf ) has said is that you could use “IP Sets” (via the ipset command) to manage all those allowed IPs with a single command, to minimize the overhead of managing too large a list, if it comes to that.

:slight_smile:

3 Likes

This topic was automatically closed 18 hours after the last reply. New replies are no longer allowed.