# Restricting SSH logins on VPS



## mgushee (Nov 19, 2009)

Hello, folks--

I recently opened a virtual private server account w/ FreeBSD 7.2
for my Web site(s). I'm a long-time Linux user and have occasion-
ally interacted as a user with other *nix systems, including FreeBSD, but this is my first time administering a BSD system.

Anyway, I would like to control SSH login privileges in the following way:

  1) Allow public key authentication for myself from anywhere.
     I may add a few other users in the future, but it should
     be few enough that I can easily list them in an AllowUsers
     rule.

  2) Allow password/keyboard-interactive login for myself from
     home (in case of emergency) and from my workplace (because 
     I have no way to secure a private key at work).

  3) Deny all other logins.

BTW, if it's not obvious, "myself" means myself under my regular
user name. I don't see a need to allow remotely logging in as
root.

So I have the following in /etc/ssh/sshd_conf:


```
AllowUsers gomez
```
     (that's a made-up username representing myself)

That seems to accomplish (1) above.

It appears that I can accomplish (2) with the following entry in
/etc/login.access:


```
-:ALL EXCEPT: gomez@88.54.129.20/32 gomez@211.41.0.0/16
```

     (where the first IP is my single static IP at home, and
      the second is the subnet at work)

Have I got that right?

Also: does /etc/login.access have any effect on su access once I am logged in remotely? If so, how do I ensure that I can su as needed?

Finally, I had a look at the authentication logs the other day,
and saw a buttload of access attempts from various locations--
a little bit worrisome. I'm thinking it might be a good idea to
have some additional protection against those whoever-they-ares.
I have heard of a Perl script called SSHBlack--can anyone comment on its safety & effectiveness? Even better, is there a Python equivalent--since I know Python well, but not Perl.

Any important questions that I haven't asked, but should?

Thanks for any tips.


----------



## SirDice (Nov 19, 2009)

Not sure about the first part of your question, I just have it configured to accept both public/private key authentication and password.

The second part is an unfortunate side effect of having ssh open to the world. I use security/sshguard-pf and I'm quite happy with it.
You can also use sshguard with the other firewalls (different port/pkg, all start with sshguard-*). There are also some alternatives.


----------



## DutchDaemon (Nov 19, 2009)

Apparently this is entirely possible in sshd_config


```
AllowUsers username@ip
```


----------



## anomie (Nov 19, 2009)

What OP's describing should be entirely doable. 

Make sure the following sshd_config directives are in place: 

 *PubkeyAuthentication yes*
 *ChallengeResponseAuthentication yes*
 *UsePAM yes*

It is important that you disable _all_ other authentication forms explicitly, or you may be defeating your plan. 

On FreeBSD systems, "ChallengeResponseAuthentication" basically means "authenticate using PAM". So you are correct to put the access rules in login.access(5) -- these utilize pam_login_access(8), which means the rules should only apply to ChallengeResponseAuthentication. 

The problem with putting username@host patterns directly in sshd_config is they will interfere with the "PubkeyAuthentication from anywhere" requirement. 



			
				mgushee said:
			
		

> Also: does /etc/login.access have any effect on su access once I am logged in remotely?



Nope, unless you are calling pam_login_access in /etc/pam.d/su as part of your auth stack. (That is not in place by default.)


----------



## anomie (Nov 19, 2009)

anomie said:
			
		

> So you are correct to put the access rules in login.access(5) -- these utilize pam_login_access(8), which means the rules should only apply to ChallengeResponseAuthentication.



BTW, if you find that to _not_ be the case, it can be corrected with some PAM tweaking. (You can move the pam_login_access call from the account stack to the auth stack.)


----------



## mgushee (Nov 20, 2009)

Thanks to all for the good information; I think this should be enough to get me going. Hmm, I think I like this forum--reminds me of Linux mailing lists back when I was a newbie, (shortly) before everybody started whining about how 'GIMP sucks cuz it isn't exactly like PhotoShop' and all that stuff.


----------



## mgushee (Nov 20, 2009)

anomie said:
			
		

> > Also: does /etc/login.access have any effect on su access once I am logged in remotely?
> 
> 
> 
> Nope, unless you are calling pam_login_access in /etc/pam.d/su as part of your auth stack. (That is not in place by default.)



Argh! I guess I misunderstood something here, because I've hosed myself again. I put the following in /etc/login.access:


```
+:<my_user_name>:<my_home_ip> <my_work_subnet>
-:ALL:ALL
```

Now I can log in under my regular user account, but I can't su to root :-( My /etc/pam.d/su looks like this:


```
auth            sufficient      pam_rootok.so           no_warn
auth            sufficient      pam_self.so             no_warn
auth            requisite       pam_group.so            no_warn group=wheel root_only fail_safe
auth            include         system

# account
account         include         system

# session
session         required        pam_permit.so
```

I guess the references to *pam_*.so* should have tipped me off, huh?

Anyway, moving forward, once I get tech support to save my sorry *** again ... should I then:


Disable pam_login_access for su?
Add [font="Lucida Console"]+:root:console[/font] to /etc/login.access? or
Something else?

Please advise.


----------



## anomie (Nov 20, 2009)

Sorry - I didn't give you enough information to do this properly. Note that in your /etc/pam.d/su file, the account stack includes *system*. If you take a look at /etc/pam.d/system, you'll see that it calls pam_login_access. 

It's going to require a bit of testing (so _keep a root shell open_, just in case), but I think you can simply add: 

```
+ : root : LOCAL
```

That will allow non-network logins, and should fix you up.


----------



## vivek (Nov 20, 2009)

You can throttle user login with pf itself. By default root login is not allowed. Only normal user can login over ssh and su - them. However, most hosting companies changes this so that root can get into it. Take a look at my previous security thread:
http://forums.freebsd.org/showthread.php?t=4108
This pdf describes 20 open ssh security tips including pf rules:

http://static.cyberciti.biz/tips/5489.pdf?k=366b72e072c5133316a4683e985a28bb

Good luck!


----------



## mgushee (Nov 21, 2009)

anomie said:
			
		

> Sorry - I didn't give you enough information to do this properly. Note that in your /etc/pam.d/su file, the account stack includes *system*.



Well, I wasn't paying close enough attention. I [usually] know what *include* means. Oh well.



> but I think you can simply add:
> 
> ```
> + : root : LOCAL
> ```



Yes, that worked. But now I'm wondering: the manual page says that the LOCAL keyword matches any string not containing '.'. So how hard would it be for a determined cracker to spoof that?

I also discovered the right way to specify an IP subnet. Before, I was trying to do it like this:


```
4.5.6.0/24
```

But that doesn't work. You have to write:


```
4.5.6.
```

Is that a commonly used notation? I don't think I've seen it before (be it noted that I'm not exactly a networking guru).


----------



## anomie (Nov 21, 2009)

Don't quote me on this, but I think it would be difficult to trick PAM into believing a network login is coming from a local terminal. 

You'll see the "4.5.6." notation from time to time for application-level IP access control. A couple other examples which honor that notation are: Apache web server, CUPS, and tcp wrappers (hosts.allow).


----------



## mgushee (Nov 23, 2009)

*Update*

Ok, well, the good news is that I haven't locked myself out again--at least not irretrievably. The bad news is that, while I can log in with either a password or a public key from the locations designated in /etc/login.access, I can't log in at all from anywhere else, which is not quite what I want.

It appears that PAM is being invoked regardless of the authentication method--which is probably a good thing, except that I can't see a way in the PAM configuration to restrict logins by location _and_ authentication method. Again, my goals are to:

 * Allow ssh logins only by myself, under my regular username;

 * Allow password authentication from a small set of known 
   locations; and

 * Allow login via public key authentication from anywhere.

So it seems that I can either:

 a) Tell PAM to restrict password auth by location, but not
    public key auth--but this doesn't appear to be possible.

or

 b) Tell sshd to use PAM only for password auth.

Couple of questions related to (b): I

 * Is the order of the directives in sshd_config important? I 
   haven't been able to find any statement in the docs about 
   that.
 * What would be the consequences of disabling PAM for sshd 
   entirely? and finally,
 * Given that there is an sshd policy in /etc/pam.d, does
   putting UsePAM no in sshd_config really disable PAM for
   sshd?

Thanks for any info!


----------



## anomie (Nov 24, 2009)

I'll tinker with this tomorrow if I have a chance. What you're attempting to do should be possible (with some PAM tweaking). 



			
				mgushee said:
			
		

> Is the order of the directives in sshd_config important?



No. 



			
				mgushee said:
			
		

> What would be the consequences of disabling PAM for sshd entirely?



I believe that would break ChallengeResponse Authentication. (Keep that root shell open in case it does..) 



			
				mgushee said:
			
		

> Given that there is an sshd policy in /etc/pam.d, does putting UsePAM no in sshd_config really disable PAM for sshd?



I believe so (but haven't tested). Support for PAM is compiled into sshd, but if you tell him not to use PAM, he should ignore /etc/pam.d/sshd.


----------



## anomie (Nov 24, 2009)

anomie said:
			
		

> BTW, if you find that to _not_ be the case, it can be corrected with some PAM tweaking. (You can move the pam_login_access call from the account stack to the auth stack.)



It appears I'm 0/2 on this thread. My intention was to put both pam_ssh(8) and pam_login_access(8) in the auth stack, and then making the former sufficient and the latter required. (i.e. If pubkey authentication works, we're in. If not, but challenge-response authentication works, we're in. If not, goodbye.) 

My idea was hamstrung by one teensy detail: 

```
The login.access service module for PAM, pam_login_access provides func-
     tionality for only one PAM category: account management.  In terms of the
     module-type parameter, this is the ``account'' feature.
```

You _can't_ move it to the auth stack, because it doesn't handle that category. :\

-------

In an attempt to save face, I offer you this: 

To achieve your initial goal, you can run two sshd instances -- one which only accepts pubkey authentication, and one which only accepts challenge-response authentication (with access control managed by pam_login_access). This would be possible if, e.g., you run the base system sshd on one IP and security/openssh-portable on another IP (or another port on the same IP). [ edit: I have not tested this approach, so you'd need to give this a try to confirm. This is my official out -- no more apologies for giving advice that does not work. ]

... or...

You can focus on making sshd a harder target other ways, such as enforcing strong passwords for shell users.


----------



## mgushee (Nov 24, 2009)

anomie said:
			
		

> It appears I'm 0/2 on this thread.
> 
> ....
> 
> ...



Interesting ideas. On further consideration, though, I can probably do without password auth entirely. I think I have a solution to the lack of secure storage at my workplace ... and in the unlikely event that sshd crashes, I can still have tech support restart it.

Still, I learned a lot from this discussion, and I appreciate all the work you put into it.


----------

