How to allow only certain users to login to an SSH server from a particular network interface?
e.g.
- eth0 is "outside", eth1 is "inside".
- user1 is trusted to login from anywhere
- user2 is only allowed to login from "inside"
Can't use AllowUsers user1@eth0
because AllowUsers takes a hostname not an interface name.
Other answers on this site suggest something like:
Match address 1.2.3.4/16 # eth0's network
AllowUsers user1
Match address 2.3.4.5/16 # eth1's network
AllowUsers user1,user2
Match address 0.0.0.0/0 # Match's equivalent of a closing brace?
However if eth0 is using a DHCP server to get its address, then it doesn't know in advance that 1.2.3.4 is the right address to put in sshd_config.
(OpenSSH on Ubuntu 12.04 if that makes a difference)
I know this is an old question but I was looking for a solution without having to start 2 instances of sshd.
Referring to your specific question and the 1.2.3.4/16 subnet and the 2.3.4.5/16 subnet, you could use the following:
Reference: http://www.unixlore.net/articles/five-minutes-to-even-more-secure-ssh.html
For my network, I use the following to allow user chris to ssh from anywhere but only allow user1, user2 and user3 to ssh on my internal network (192.168.0.0/24):
Version: SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3 on Ubuntu 14.04.3 LTS
I don't know how to do this in a
Match
block, and your comment above suggests it's not possible (as does, as you note, theman
page).But if you're sure that you want to do the user restriction by interface - which your questions says you do - you could run two
sshd
s, each having a differentsshd_config
which directs it to listen on one interface only, controlled by theListenAddress
directive.The
sshd
listening on the internal interface could in its config haveAllowUsers user1 user2
, while that listening on the external interface could haveAllowUsers user1
. I'd probably do it by group membership and haveAllowGroups internal
/AllowGroups internal external
instead, but that's just me.Edit: imo, the right way to do this is to run
/usr/sbin/sshd -f /etc/ssh/sshd_config_inside
and/usr/sbin/sshd -f /etc/ssh/sshd_config_outside
. Arranging how this works at boot time, and ensuring that your service startup/shutdown files do the right thing, is indeed important, but it is also a perfectly normal thing for a sysadmin to need to do, and to do. It is definitely not necessary to have two binaries, or even the same binary by two different names, to do this.Match address 1.2.3.4/16
is invalid, must beMatch address 1.2.0.0/16
. The network addresses of the interfaces don't change, do they? So it doesn't matter what IP you get.Another option may be (I have no personal experience with that) to create two virtual interfaces with a static address, have two sshd instances, each bound to one of these addresses only and make DNAT from the DHCP interface to the virtual one.
Maybe you could write a small script to get the current eth0 address (from ifconfig?) and to set in your sshd_config (using sed); if I remember correctly it's also possible to write hook scripts to be executed everytime an ethernet interface goes down/up (this could solve the necessity to update manually or via crontab you sshd_config file).
Match Adress
andMatch User
should work and since a couple of months, since OpenSSH 7.7, at least if you believe the bug reports here you can also have negating matches.If you want to lock down your SSH with
sshd_config
, the caveat is that you should disable password and pubkey based logins for anyone else.For example:
sshd_config
This way, it doesn't matter how many interfaces your server has and which DHCP address they get - it matters where the users are connecting from, which is what should concern you.
The short answer: You can't.
The long answer: You shan't.
It's only a pseudo-gain in terms of security. You should think over you security concept first.
But, in interest of professional discussion, you can with fugly hacks: