The problem with handling this by changing login shell, as in your example, is that when user connects to
sshd in the main network namespace then even if you get their shell to run inside another namespace but their port forwarding will operate in the default network namespace anyway.
My proposed solution also addresses containing port forwarding to the namespace as well as the shell. It is probably limited to using local accounts, as authenticating against remote system over the network (NIS, SMB etc) will probably not work because authentication stage will be executed from within the network namespace.
I needed both the shell and port forwarding to operate in the target namespace without creating networking/routing between default and contained namespaces.
Here are a few methods/tools to achieve this:
xinetd - Thanks Stéphane Chazelas for pointing it out.
For a single or static number of namespaces and forwarding to them
xinetd seems a better option.
type = UNLISTED
socket_type = stream
protocol = tcp
port = 222
wait = no
user = root
server = /sbin/ip
server_args = netns exec NameSpaceName /usr/sbin/sshd -i
for multiple namespaces where forwarding to them needs to be started/stopped independently
socat is a good fit.
Run this in the default namespace:
socat tcp-listen:222,fork,reuseaddr \
exec:'ip netns exec NameSpaceName /usr/sbin/sshd -i',nofork
socat is not available then
ncat (on my RHEL box as
nc) can do the job.
ncat is the
sshd is connected to
ncat via a pipe rather than directly to the socket so
sshd can not see client IP with all following consequences.
You also end up running on extra intermediate
ncat --keep-open --sh-exec "exec ip netns exec NameSpaceName /usr/sbin/sshd -i" -l 222
and probably other tools.
This accepts SSH connections in the default namespace on a custom port 222 and for each connection starts one time
sshd -i inside the target namespace.
That solved it for me, but you also have a requirement of limiting users that can login to each namespace. Create a namespace specific sshd config:
mkdir -pv /etc/netns/NameSpaceName/
cp -Rp /etc/ssh /etc/netns/NameSpaceName/
Add access controls to each
sshd_config file, e.g. in default
AllowUsers user1 user2
... and in
AllowUsers restrictedUser1 restrictedUser2
... also look at
now re-create the namespace for the dir binds to become effective
My brief tests show user access control works as expected, but I have not really used it much so its is for you to validate.
I tried putting separate
/etc/group files into
/etc/netns/NameSpaceName/ for having separate list of users, but in my quick test that did not work:
useradd test inside the namespace fails.
If you don't like custom port you could dual home e.g. macvlan or just add another IP address and listen on the default port on a dedicated IP.
All authentication, shell, subsystem, port forwarding etc is handled by the
sshd so I don't have to hack anything else.
It does have drawback of running
sshd -i like this, read
man sshd look for
-i option. You could easily solve it by running a full time
sshd inside the namespace and change the forwarding daemon to something like this:
nc --keep-open --sh-exec "exec ip netns exec NameSpaceName nc localhost 22" -l 222
I wonder if mount and/or user namespaces (in addition to network namespaces) could be used to solve it more neatly. I have no experience with those.
There probably are better ways to achieve this, I'd be very interested in what others come up with.