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

How to implement security/authorization #296

Closed
Porco-Rosso opened this issue Apr 27, 2016 · 12 comments
Closed

How to implement security/authorization #296

Porco-Rosso opened this issue Apr 27, 2016 · 12 comments

Comments

@Porco-Rosso
Copy link

Hi,
I've recently set up a sync-engine instance on a home VM, how would I go about allowing N1 to connect to it from outside the network in a safe way?
As I understand correctly there is a security concern simply exposing port 5555, as anybody can query for accounts and account Ids.

I've seen #104 and #115 but still don't quite understand.

@spikenheimer
Copy link

until there is a sync-engine based security answer, one solution would be to VPN into your home network from the outside.

@khamidou
Copy link
Contributor

Hi @Porco-Rosso,

I would recommend:

  1. Running the sync-engine behind a VPN
  2. Putting nginx in front of the API and limiting the access to /accounts
  3. Using HTTPS

Thanks!

k

@Porco-Rosso
Copy link
Author

Porco-Rosso commented Jul 18, 2016

Hi @khamidou

Sorry for commenting on a closed issue. But with the rolling-out of nylas as a paid service, I would really like to get this working.

As I understand your three suggestions are supposed to be employed together, not as separate options.

I would really like to host the nylas-sync engine on my home server in a VM and be able to access it from outside my network securely. However, I do not want to have to rely on always connecting to my vpn in order to just receive and send emails.

Is there any way I can achieve this? any insight would be much appreciated!

PS: could you please re-open the issue?

@egyptianbman
Copy link

Thank you @khamidou for providing the missing link (for me) in getting this done. Hopefully this will help others, the following is what I have and it's working well. You definitely need to do your own research to figure out how to get everything working together.

Run nylas-sync as a docker container

I use the following docker-compose.yml file to keep from having to run a bunch of docker commands:

version: "2"

services:
  app:
    build:
      context: .
    network_mode: bridge
    ports:
      - 5555
    volumes:
      - ./nylas_part:/var/lib/inboxapp
    environment:
      - VIRTUAL_HOST=REPLACE_WITH_HOST_NAME
      - VIRTUAL_PROTO=http
      - VIRTUAL_PORT=443
      - HTTPS_METHOD=nohttp
      - CERT_NAME=REPLACE_WITH_HOST_NAME
    links:
      - mysql
      - redis
    # logging:
    #   driver: "json-file"
    #   options:
    #     max-size: 50k

  mysql:
    image: mysql
    network_mode: bridge
    environment:
      - MYSQL_ROOT_PASSWORD=root
    volumes:
      - ./nylas_mysql:/var/lib/mysql
    # logging:
    #   driver: "json-file"
    #   options:
    #     max-size: 50k

  redis:
    image: redis
    network_mode: bridge
    volumes:
      - ./nylas_redis:/data
    # logging:
    #   driver: "json-file"
    #   options:
    #     max-size: 50k

# vim:set ft=yaml ts=2 sw=2 smarttab:

Read the documentation for the container on how to add your accounts to the container

Serve nylas-sync via an nginx proxy container

I use an alias to start/restart/update my nginx proxy container:

alias dkr-proxy="docker stop proxy && docker rm proxy; docker pull jwilder/nginx-proxy && docker run --name proxy -d -p 80:80 -p 443:443 -v /var/run/docker.sock:/tmp/docker.sock -v ${HOME}/junk/.nginx-vhost.d/:/etc/nginx/vhost.d -v ${HOME}/junk/.nginx-htpasswd/:/etc/nginx/htpasswd -v ${HOME}/junk/.lets-encrypt/letsencrypt.sh/certs/all:/etc/nginx/certs --log-driver json-file --log-opt max-size=50k --net bridge -it jwilder/nginx-proxy"

There are a few things to note in this alias:

  • I use a ${HOME}/junk directory to hold various files/directories for projects. You'll notice I'm mounting three "volumes" into the container:
    • junk/.nginx-vhosts.d/REPLACE_WITH_HOST_NAME has a file that appends the following nginx configuration:
# Require authentication for the /accounts uri.

location /accounts {
    auth_basic "Only Beshoy!";
    auth_basic_user_file /etc/nginx/htpasswd/REPLACE_WITH_HOST_NAME;
    proxy_pass http://REPLACE_WITH_HOST_NAME;
}
  • junk/.nginx/htpasswd/REPLACE_WITH_HOST_NAME has a file that holds my htpasswd creds for the nylas hostname. You can generate the file by running:
$ htpasswd -c ${HOME}/junk/.nginx-htpasswd/REPLACE_WITH_HOST_NAME REPLACE_WITH_USERNAME

proxy continued: lets-encrypt ssl certificates:

There are a bunch of ways you can do this (if you want to use lets-encrypt certificates). You have to generate a new cert every three months which isn't ideal but they are free and they work well. My setup is too long to add here so I'll leave this to you to scour the internet for examples

N1 Client

Last but not least, you need to tell your nylas client to use the ssl and to authenticate via the htpasswd credentials you created previously. While the nylas UI for a self-hosted sync engine doesn't provide an interface for adding the credentials, you can simply tell it the sync engine hostname as https://REPLACE_WITH_HTPASSWD_USER:REPLACE_WITH_HTPASSWD_PASSWORD@REPLACE_WITH_HOST_NAME

This probably goes without saying but don't forget to make sure your router is routing port 443 to the machine that is running all of this. I wish you luck in the setup. I ran into issues with the nylas sync container and getting lets-encrypt to (almost) be fully automated which slowed down the process a bit but once it's all up and running, it's quite stable.

@Porco-Rosso
Copy link
Author

Thank you for finally figuring out how to add authentication! Going to try this out soon.

@dcrystalj
Copy link

if u ask me this is intensionally complicated. I started to dislike this nylas. looks evil

@egyptianbman
Copy link

@dcrystalj, I can't say that I agree with you.

  1. The Nylas sync engine + N1 application are open sourced. A very small number of companies do this.
  2. The way this application is structured is indeed complex. This is by design. They've opted to introduce complexity and benefit from providing flexibility to their customers. To me, this is a fair decision. While this is complex to set up, it doesn't make sense for them to cut out functionality to make the free version easier to run. In addition, this provided them a business case since most people don't want to or can't build such infrastructure. There's nothing wrong with a business wanting to make a profit.

I don't trust my e-mails to anyone -- it's why I opt to build and run it myself. The fact that that's an option causes me to appreciate the work Nylas does, and what they've provided us. There are dozens of e-mail apps out there but for Linux, none are as beautiful or work as well as N1. There are also other cloud-based e-mail providers that don't open source anything. If more companies ran like Nylas, the software world would be a much better place.

@dcrystalj
Copy link

well open source is future thats why nylas is interesting.
But instead of doing this

https://REPLACE_WITH_HTPASSWD_USER:REPLACE_WITH_HTPASSWD_PASSWORD@REPLACE_WITH_HOST_NAME

there could be one simple basic auth with username and password without ssl dont u think so?

@egyptianbman
Copy link

You don't have to do ssl. The issue with that however is your credentials are traveling through the net unencrypted and easily sniffed out. At that point, you probably don't even need to bother with the basic authentication.

@dcrystalj
Copy link

but i was able to load emails with sync-engine just by pointing my n1 client to correct ip and port without password. That is what bothers me

@egyptianbman
Copy link

If you're using the nginx proxy, port 5555 shouldn't be bound to the host machine.

@cowboycodur
Copy link

cowboycodur commented Mar 2, 2017

I got this working with a setup similar to this

sync-proxy:
  image: nginx
  ports:
    - 5555:5555
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
    - ./htpasswd:/etc/nginx/htpasswd:ro
  links:
    - sync-engine:sync-engine

sync-engine:
  image: nhurel/nylas-sync-engine
  volumes:
    - nylas_part:/var/lib/inboxapp
  links:
    - mysql:mysql
    - redis:redis
  hostname: sync-engine
  log_opt:
    max-size: "10m"
    max-file: "10"
mysql:
  image: mysql
  environment:
    - MYSQL_ROOT_PASSWORD=root
  volumes:
    - nylas_mysql:/var/lib/mysql
  log_opt:
    max-size: "10m"
    max-file: "10"

redis:
  image: redis
  volumes:
    - nylas_redis:/data
  log_opt:
    max-size: "10m"
    max-file: "10"

with an nginx.con like this

events {
  worker_connections  1024;
}

http {

        upstream apiserver {
                server sync-engine:5555;
        }

        server {
                listen 5555;

                location /accounts {
                         auth_basic "Authentication";
                         auth_basic_user_file /etc/nginx/htpasswd;

                        proxy_pass http://apiserver;
                        proxy_redirect off;
                }

                location / {
                        proxy_pass http://apiserver;
                        proxy_redirect off;
                }
        }
}

with the N1 config.json containing APIRoot of "http://user:pass@localhost:5555"

YOU CANNOT password protect anything other than /accounts or syncing fails, this maybe ok as it looks like the sync-engine has its own basic auth for everything but /accounts

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

6 participants