Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider better security defaults #46

Open
hadley opened this issue Sep 30, 2014 · 31 comments
Open

Consider better security defaults #46

hadley opened this issue Sep 30, 2014 · 31 comments

Comments

@hadley
Copy link
Collaborator

hadley commented Sep 30, 2014

Not sure what these should be. Some ideas:

@sckott
Copy link
Collaborator

sckott commented Sep 30, 2014

@cboettig
Copy link
Contributor

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.

@sckott
Copy link
Collaborator

sckott commented Oct 1, 2014

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

@sckott
Copy link
Collaborator

sckott commented Oct 2, 2014

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 2, 2014

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.

@sckott
Copy link
Collaborator

sckott commented Oct 2, 2014

right, ok

@hadley
Copy link
Collaborator Author

hadley commented Oct 3, 2014

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.

@cboettig
Copy link
Contributor

cboettig commented Oct 6, 2014

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 15, 2014

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

@cboettig
Copy link
Contributor

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 notifications@github.com
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
#46 (comment).

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 17, 2014

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

@cboettig
Copy link
Contributor

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 notifications@github.com
wrote:

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


Reply to this email directly or view it on GitHub
#46 (comment).

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 17, 2014

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 notifications@github.com
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 <notifications@github.com
javascript:_e(%7B%7D,'cvml','notifications@github.com');>
wrote:

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


Reply to this email directly or view it on GitHub
#46 (comment).

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


Reply to this email directly or view it on GitHub
#46 (comment).

http://had.co.nz/

@cboettig
Copy link
Contributor

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 notifications@github.com
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 notifications@github.com
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 <
notifications@github.com
javascript:_e(%7B%7D,'cvml','notifications@github.com');>
wrote:

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


Reply to this email directly or view it on GitHub
#46 (comment).

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


Reply to this email directly or view it on GitHub
#46 (comment).

http://had.co.nz/


Reply to this email directly or view it on GitHub
#46 (comment).

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 20, 2014

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
Copy link
Collaborator Author

hadley commented Oct 20, 2014

@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.

@cboettig
Copy link
Contributor

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.

@hadley
Copy link
Collaborator Author

hadley commented Oct 20, 2014

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

@cboettig
Copy link
Contributor

nice!

On Mon, Oct 20, 2014 at 2:25 PM, Hadley Wickham notifications@github.com
wrote:

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

#cloud-configusers:

  • name: analogsea
    ssh-authorized-keys:
    • ssh-rsa
      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
#46 (comment).

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

@sckott
Copy link
Collaborator

sckott commented Oct 20, 2014

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

@hadley
Copy link
Collaborator Author

hadley commented Oct 20, 2014

@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.

@cboettig
Copy link
Contributor

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 notifications@github.com
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
#46 (comment).

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

@sckott
Copy link
Collaborator

sckott commented Oct 20, 2014

@hadley sounds good

@hadley
Copy link
Collaborator Author

hadley commented Oct 20, 2014

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

hadley added a commit that referenced this issue Oct 21, 2014
hadley added a commit that referenced this issue Oct 21, 2014
Because yaml drops comments. #46
@hadley
Copy link
Collaborator Author

hadley commented Oct 21, 2014

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.

@cboettig
Copy link
Contributor

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" notifications@github.com 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
#46 (comment).

@sckott
Copy link
Collaborator

sckott commented Nov 28, 2014

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?

@hrbrmstr
Copy link

hrbrmstr commented Feb 9, 2017

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?

@sckott
Copy link
Collaborator

sckott commented Feb 9, 2017

+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.

@hrbrmstr
Copy link

hrbrmstr commented Feb 9, 2017

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.

@sckott
Copy link
Collaborator

sckott commented Feb 9, 2017

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants