I don't see a possibility to force sockets to a certain port but you can prevent other ports being successfully used. This can be done by iptables
and its owner
module. You can drop all replies from processes belonging to this user from disallowed addresses.
If this is an option for you and you don't know how to do it let me know and I will deliver some code in addition.
Edit 1
The solution is to block every packet from this user which belongs
- neither to a connection which this user has opened (i.e. he is not listening on a port at all)
- nor sends from an allowed port.
You are right, owner
does not work in INPUT but we need it in OUTPUT only. To make things easier (and faster) we mark all allowed packets (from this user) with 42, all disallowed with 41. Marking the disallowed ones would be enough.
It works this way:
- All packets (connections) from that user are selected for special handling
- All packets are marked with 41 (disallowed). For allowed connections this is overwritten later.
- All connections with a locally generated first packet are allowed
- Everything left was not created locally. Drop everything not from lo
- Now allow all connections with an allowed source port (sorce of the reply i.e. local port)
- Last step: Drop all packets which are marked with 41.
Edit 2
The approach with the nat
table failed (for incoming connections because only the first packet of a connection is checked in nat
and the first is the incoming one which hits -t nat INPUT
only where the owner
module is not available). Thus all checking and marking is done in the default table (filter
) now.
The script:
#!/bin/bash
# MODIFY NEXT LINE
user=hl
# iptables -F
# iptables -t nat -F
# iptables -t mangle -F
iptables -N user_x &>/dev/null
iptables -N user_x_ports &>/dev/null
iptables -N user_x_allow &>/dev/null
iptables -N user_x_block &>/dev/null
# configure chain user_x_allow
iptables -A user_x_allow -j CONNMARK --set-mark 42
iptables -A user_x_allow -j ACCEPT
# configure chain user_x_block
iptables -A user_x_block -j CONNMARK --set-mark 41
iptables -A user_x_block -j DROP
# configure chain user_x_ports
# one line for each allowed port
iptables -A user_x_ports -p tcp --sport 1234 -j user_x_allow
# configure chain user_x
iptables -A user_x -m conntrack --ctstate NEW -j user_x_allow
iptables -A user_x \! -o lo -j user_x_block
iptables -A user_x -j user_x_ports
iptables -A user_x -j user_x_block
# the first two rules are just for checking what happens with "iptables -L -nv"
# and can be commented out
index=1
iptables -I OUTPUT "$index" -m owner --uid-owner $user; ((index++)) # just count
iptables -I OUTPUT "$index" -m owner --uid-owner $user -m connmark --mark 0; ((index++)) # just count
iptables -I OUTPUT "$index" -m connmark --mark 41 -j DROP # or reset
((index++))
iptables -I OUTPUT "$index" -m connmark --mark 42 -j ACCEPT
((index++))
# this matches non-marked (new) connections only
iptables -I OUTPUT "$index" -m owner --uid-owner $user -j user_x
((index++))