analogsea icon indicating copy to clipboard operation
analogsea copied to clipboard

Consider better security defaults

Open hadley opened this issue 9 years ago • 31 comments

Not sure what these should be. Some ideas:

  • Create non-root user
  • Add basic firewall
  • Other stuff from here: https://www.digitalocean.com/community/tutorials/an-introduction-to-securing-your-linux-vps

hadley avatar Sep 30 '14 21:09 hadley

  • firewall Maybe start with the easiest solution (ufw) https://www.digitalocean.com/community/tutorials/how-to-setup-a-firewall-with-ufw-on-an-ubuntu-and-debian-cloud-server which they describe as generally a good choice
  • non-root user hmmm, after reading the bit on this, still not sure if needed or not, or should it definitely be done? @cboettig any thoughts?
  • ssh login they say prefer ssh keys over passwords, which we should suggest to users i think

sckott avatar Sep 30 '14 23:09 sckott

Yeah, I think we've been reading the same digitalocean docs ;-)

Here's what I've been doing: http://www.carlboettiger.info/2014/09/08/server-security-basics.html

Happy to learn more from others. I started drafting a script (very minimal, not working yet) to help automate some of this, though I think it may be hard to automate some steps (e.g. tripwire config, though maybe that's not necessary unless the user is gonna be checking the logs regularly.

I'm hoping to get a more professional consultation on this stuff eventually. Computer security is above my pay grade.

cboettig avatar Sep 30 '14 23:09 cboettig

@cboettig thanks for the quick feedback and the script share!

sckott avatar Oct 01 '14 00:10 sckott

We still need to consider better security defaults whether or not a user uses docker, right?

sckott avatar Oct 02 '14 20:10 sckott

Yes, I think so. I think more functions along the lines of install.r would be useful - then we can just tell people, this is what we recommend you do after starting a droplet.

hadley avatar Oct 02 '14 20:10 hadley

right, ok

sckott avatar Oct 02 '14 20:10 sckott

I think the first step should be to set up a non-root user. I think we can make this seamless by using Sys.info()[["user"]] to use the same user name as your local login. Then (following along from https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04):

  • Create a new user with adduser
  • Configure user for passwordless login (should just be copying a file)
  • Add line to sudo config
  • Modify default ssh port - I think using the same non-standard port for all droplets would be fine.
  • Disable root login via ssh
  • Reload ssh

I think using root is fine (for now) inside containers, but we should be a bit stricter at the top level. The only potential downside I see to this is that since we're changing ssh defaults, it may mean some small breakage if you're connecting to a droplet that you created previously.

Then apply @cboettig's script to install ufw and set up a minimal firewall. (I think we also need to allow http so that we can talk to RStudio by default)

We're already defaulting to using ssh keys if they're available. The main question is if we should require them or not. If required, we need to tweak droplet_create() and ensure password-based logins on the server are disabled.

hadley avatar Oct 03 '14 13:10 hadley

Just a note I've updated my script, though could no doubt be much improved.

  • It does the user configurations for ssh Hadley mentions above (though with sed edits, @hadley 's suggestion of just scp in an etc/ssh/sshd_config file is probably preferable, though still has to be edited interactively to get the correct username to whitelist and the correct ssh port to configure). Requires ssh keys (perhaps that's not ideal; digitalocean certainly seems to think it has enough users who prefer getting emailed passwords to make that the default).
  • It sets up the firewall, expecting you to define the ports used for SSH and RStudio (or it will use the defaults).
  • Runs some other things, including a system update.

(Obviously the script is more of a starting place to adapt than something designed for analogsea directly, just thought I'd note that it was somewhat more useful than it was earlier. Feedback/critique always appreciated) https://github.com/cboettig/dockerfiles/blob/master/setup.sh

cboettig avatar Oct 06 '14 21:10 cboettig

Looks like provides some good suggestions for setting up non root user with sudo privileges: https://www.digitalocean.com/community/tutorials/how-to-use-cloud-config-for-your-initial-server-setup

hadley avatar Oct 15 '14 21:10 hadley

Very nice! I really like the approach they take here, that's really how it should be done.

On Wed, Oct 15, 2014 at 2:00 PM, Hadley Wickham [email protected] wrote:

Looks like provides some good suggestions for setting up non root user with sudo privileges: https://www.digitalocean.com/community/tutorials/how-to-use-cloud-config-for-your-initial-server-setup

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59275413.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

cboettig avatar Oct 15 '14 21:10 cboettig

Is there a significant number we should use for the ssh port?

hadley avatar Oct 17 '14 14:10 hadley

Good question. Presumably the function we use will allow the user to choose their own value for the port, in which case it's tempting to make the default into the ssh default (22) for consistency. For a more secure default I guess we simply want to pick something that isn't commonly used for another purpose (or more strictly speaking, hasn't been registered as the default for some other protocol, see: http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml )

On Fri, Oct 17, 2014 at 7:25 AM, Hadley Wickham [email protected] wrote:

Is there a significant number we should use for the ssh port?

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59520261.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

cboettig avatar Oct 17 '14 16:10 cboettig

I don't think we should allow people to choose their own ports. It adds a lot of extra hassle for very little extra security.

On Friday, October 17, 2014, Carl Boettiger [email protected] wrote:

Good question. Presumably the function we use will allow the user to choose their own value for the port, in which case it's tempting to make the default into the ssh default (22) for consistency. For a more secure default I guess we simply want to pick something that isn't commonly used for another purpose (or more strictly speaking, hasn't been registered as the default for some other protocol, see:

http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml )

On Fri, Oct 17, 2014 at 7:25 AM, Hadley Wickham <[email protected] javascript:_e(%7B%7D,'cvml','[email protected]');> wrote:

Is there a significant number we should use for the ssh port?

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59520261.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59535851.

http://had.co.nz/

hadley avatar Oct 17 '14 17:10 hadley

I was thinking flexibility might be more along the lines of a user who just happens to be running some other service on the port we happen to choose; I imagine that's the main reason applications let you specify different ports. But that's really unlikely (unless we chose some really silly value) so I guess not worth the hassle

On Fri, Oct 17, 2014 at 10:55 AM, Hadley Wickham [email protected] wrote:

I don't think we should allow people to choose their own ports. It adds a lot of extra hassle for very little extra security.

On Friday, October 17, 2014, Carl Boettiger [email protected] wrote:

Good question. Presumably the function we use will allow the user to choose their own value for the port, in which case it's tempting to make the default into the ssh default (22) for consistency. For a more secure default I guess we simply want to pick something that isn't commonly used for another purpose (or more strictly speaking, hasn't been registered as the default for some other protocol, see:

http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml )

On Fri, Oct 17, 2014 at 7:25 AM, Hadley Wickham < [email protected] javascript:_e(%7B%7D,'cvml','[email protected]');> wrote:

Is there a significant number we should use for the ssh port?

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59520261.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59535851.

http://had.co.nz/

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59550557.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

cboettig avatar Oct 17 '14 17:10 cboettig

How does this look for a basic config? It:

  • sets up a non-root login (analogsea) with sudo privileges (will need to update all existing scripts to use sudo)
  • sets custom port for ssh (6737 = substr(gsub("[a-f]", "", digest::digest("analogsea")), 1, 4)), forbids root login, and only allows password-less login for analogsea user
  • sets shell to bash

If we use this system, it will make it harder to access older droplets, because we'll need to change the defaults for user name and ssh port. I think that's ok - it's a one time breaking change, and substantially improves the default security.

#cloud-config
users:
  - name: analogsea
    ssh-authorized-keys:
      - ssh-rsa <SSH-KEY>
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    groups: sudo
    shell: /bin/bash
write_files:
  - path: /etc/ssh/sshd_config
    content: |
      Port 6737
      Protocol 2
      HostKey /etc/ssh/ssh_host_rsa_key
      HostKey /etc/ssh/ssh_host_dsa_key
      HostKey /etc/ssh/ssh_host_ecdsa_key
      HostKey /etc/ssh/ssh_host_ed25519_key
      UsePrivilegeSeparation yes
      KeyRegenerationInterval 3600
      ServerKeyBits 1024
      SyslogFacility AUTH
      LogLevel INFO
      LoginGraceTime 120
      PermitRootLogin no
      AllowUsers analogsea
      StrictModes yes
      RSAAuthentication yes
      PubkeyAuthentication yes
      IgnoreRhosts yes
      RhostsRSAAuthentication no
      HostbasedAuthentication no
      PermitEmptyPasswords no
      ChallengeResponseAuthentication no
      X11Forwarding yes
      X11DisplayOffset 10
      PrintMotd no
      PrintLastLog yes
      TCPKeepAlive yes
      AcceptEnv LANG LC_*
      Subsystem sftp /usr/lib/openssh/sftp-server
      UsePAM yes

hadley avatar Oct 20 '14 20:10 hadley

@wch has convinced me that a non-standard port is probably not that important. It adds a lot of extra hassle for only minimal extra security.

hadley avatar Oct 20 '14 20:10 hadley

This looks pretty good to me. I think you may need to add PasswordAuthentication no explicitly when you have UsePAM yes (even though I think UsePAM makes sense here), otherwise one can still authenticate using passwords instead of ssh key.

cboettig avatar Oct 20 '14 20:10 cboettig

After a bit more discussion with @wch, we have

#cloud-config
users:
  - name: analogsea
    ssh-authorized-keys:
      - ssh-rsa <SSH-KEY>
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    groups: sudo
    shell: /bin/bash
write_files:
  - path: /etc/apt/apt.conf.d/20auto-upgrades 
    content: |
      APT::Periodic::Update-Package-Lists "1";
      APT::Periodic::Unattended-Upgrade "1";
  - path: /etc/ssh/sshd_config
    content: |
      Port 22
      Protocol 2
      HostKey /etc/ssh/ssh_host_rsa_key
      HostKey /etc/ssh/ssh_host_dsa_key
      UsePrivilegeSeparation yes
      KeyRegenerationInterval 3600
      ServerKeyBits 1024
      SyslogFacility AUTH
      LogLevel INFO
      LoginGraceTime 120
      PermitRootLogin no
      AllowUsers analogsea
      StrictModes yes
      PasswordAuthentication no
      ChallengeResponseAuthentication no
      RSAAuthentication yes
      PubkeyAuthentication yes
      IgnoreRhosts yes
      RhostsRSAAuthentication no
      HostbasedAuthentication no
      PermitEmptyPasswords no
      X11Forwarding yes
      X11DisplayOffset 10
      PrintMotd no
      PrintLastLog yes
      TCPKeepAlive yes
      AcceptEnv LANG LC_*
      Subsystem sftp /usr/lib/openssh/sftp-server
      UsePAM yes
runcmd:
  - apt-get update
  - apt-get install -y unattended-upgrades

Compared to the previous version, this:

  • Keeps ssh port as 22
  • Explicitly disables PasswordAuthentication
  • Sets up automatic security updates

hadley avatar Oct 20 '14 21:10 hadley

nice!

On Mon, Oct 20, 2014 at 2:25 PM, Hadley Wickham [email protected] wrote:

After a bit more discussion with @wch https://github.com/wch, we have

#cloud-configusers:

  • name: analogsea ssh-authorized-keys:
    • ssh-rsa <SSH-KEY> sudo: ['ALL=(ALL) NOPASSWD:ALL'] groups: sudo shell: /bin/bashwrite_files:
  • path: /etc/apt/apt.conf.d/20auto-upgrades content: | APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1";
  • path: /etc/ssh/sshd_config content: | Port 22 Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key UsePrivilegeSeparation yes KeyRegenerationInterval 3600 ServerKeyBits 1024 SyslogFacility AUTH LogLevel INFO LoginGraceTime 120 PermitRootLogin no AllowUsers analogsea StrictModes yes PasswordAuthentication no ChallengeResponseAuthentication no RSAAuthentication yes PubkeyAuthentication yes IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no PermitEmptyPasswords no X11Forwarding yes X11DisplayOffset 10 PrintMotd no PrintLastLog yes TCPKeepAlive yes AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server UsePAM yesruncmd:
  • apt-get update
  • apt-get install -y unattended-upgrades

Compared to the previous version, this:

  • Keeps ssh port as 22
  • Explicitly disables PasswordAuthentication
  • Sets up automatic security updates

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59842423.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

cboettig avatar Oct 20 '14 21:10 cboettig

looks great @hadley - should we allow input to modify this setup within analogsea, or just tell users to ssh in and change as needed?

sckott avatar Oct 20 '14 21:10 sckott

@sckott I'll make it a little configurable, once I turn it into an R function. But this is a script that's run once on droplet creation, so it's not possible to modify after the fact.

hadley avatar Oct 20 '14 21:10 hadley

Do you want to install & configure a ufw firewall at this time as well? Would either mean hardwiring the port used for RStudio or providing a way to ufw enable it later.

On Mon, Oct 20, 2014 at 2:36 PM, Hadley Wickham [email protected] wrote:

@sckott https://github.com/sckott I'll make it a little configurable, once I turn it into an R function. But this is a script that's run once on droplet creation, so it's not possible to modify after the fact.

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59843822.

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

cboettig avatar Oct 20 '14 21:10 cboettig

@hadley sounds good

sckott avatar Oct 20 '14 21:10 sckott

@cboettig I don't think a firewall is sufficiently useful that we should install it by default.

hadley avatar Oct 20 '14 21:10 hadley

This now appears to be working - you can use the default ubuntu config with droplet_create(cloud_config = "ubuntu").

I think the next question is whether we should enable this by default (I think so), and if so, how should we manage the transition? One option is to change the default in droplet_create() to cloud_config = "ubuntu" and then change the default username in droplet_ssh to analogsea. This will make it harder to connect to old droplets, but I think the tradeoff is worth it.

hadley avatar Oct 21 '14 15:10 hadley

I like this plan


Carl Boettiger http://carlboettiger.info

sent from mobile device; my apologies for any terseness or typos On Oct 21, 2014 8:11 AM, "Hadley Wickham" [email protected] wrote:

This now appears to be working - you can use the default ubuntu config with droplet_create(cloud_config = "ubuntu").

I think the next question is whether we should enable this by default (I think so), and if so, how should we manage the transition? One option is to change the default in droplet_create() to cloud_config = "ubuntu" and then change the default username in droplet_ssh to analogsea. This will make it harder to connect to old droplets, but I think the tradeoff is worth it.

— Reply to this email directly or view it on GitHub https://github.com/sckott/analogsea/issues/46#issuecomment-59943285.

cboettig avatar Oct 21 '14 15:10 cboettig

Hmmm, I wonder why ssh-authorized-keys (to allow specific ssh keys) is not included in the config file. Is there a reason why not?

sckott avatar Nov 28 '14 01:11 sckott

late to the party (mostly due to me resurrecting harbor and re-doing the analogsea harbor interface within harbor for it.

I have empirical evidence (this is part of what I do for a living ;-) that changing the default port to something besides 22 does in fact enhance security greatly. It's a tiny obfuscation step but thwarts a big percentage of opportunistic attackers. It won't stop a determined one but nothing will, so it's worth it to change it.

I will agree that having a different universal default ssh port embedded in analogsea is not going to improve security since once various attacker groups who scan the internet find it out (and will since I commented in here now — apologies, but I get followed around :-)

Why am I blathering on about ports? All my droplets but 1 (which is a partial honeypot as well as a functioning web server) use a different ssh port and was pretty much unable to use droplet_ssh()

@sckott any issues if I (eventually…can't promise a timeline right now) add a port='default' parameter to the functions in https://github.com/sckott/analogsea/blob/master/R/droplet-ssh.R and if it's not default then have the functions use the specified port? That way, folks like me who make a droplet outside of this pkg or reconfig one that uses this pkg can still use the commands for automation (and, eventually, harbor) but "regular" folk won't even need to worry about it?

hrbrmstr avatar Feb 09 '17 10:02 hrbrmstr

+1 for other than 22 port - what should that port be? a random port number between number x and y?

the port param sounds good to me.

sckott avatar Feb 09 '17 12:02 sckott

Aye. It could be a small-ish range, too. We could also add some links to things like https://github.com/fail2ban/fail2ban or add a helper function to install it on images. I'll noodle over some possibilities.

hrbrmstr avatar Feb 09 '17 14:02 hrbrmstr