30

I am a contractor who does development for more than one client. Let's call them Client A, Client B, and Client X.
I use my own laptop for all 3 clients.
Throughout the day, I have to work on and respond to emails and instant messages about projects for all 3 clients.

In order to work on Client X's project, I must be connected to their VPN.
Client X performs SSL deep inspection on the traffic on their network. (I get errors from sites/apps that enforce key pinning)

I'm worried that information about Client A and Client B, (not to mention my own sensitive information) might be exposed to Client X. How can I prevent this, but still maintain my ability to communicate with A and B while working on X's network?

To be clear, all my clients understand that they are not my only customer, so I'm not trying to hide the fact that I'm working on other projects, just trying to ensure that each client's "back-room" information stays private.

I've tried giving each client its own VM on my machine, but the hefty resource requirements of the software I have to use (IDE) makes this prohibitively slow, to say nothing of the licensing difficulties.

Purchasing additional hardware (and the necessary additional software licenses) would mean a significant (to me) financial expense, as well as time & headache managing the extra devices, not to mention would be physically cumbersome, so I'd really like to avoid that route.

duggulous
  • 401
  • 4
  • 8
  • 7
    Why dont you just use your mobile phone for emails during the day ? – vikingsteve Sep 16 '20 at 06:57
  • 1
    Are you only looking for a OS-configuration or software-configuration solutions? Are you open to hardware / new device solutions like vikingsteves above? – lofidevops Sep 16 '20 at 11:59
  • If Client X employs a contractor without first checking what other contracts they are working on, more fool them. If Client X did check and you lied to them, more fool you when you get found out. – alephzero Sep 16 '20 at 14:27
  • 2
    @vikingsteve that doesn't work well if you have to write a long email (or even a short email but you want to copy/paste text or do any formatting), attach files or insert screenshots. – Brad Sep 17 '20 at 02:26
  • 2
    @alephzero you can be honest about your clients and still not want to expose their confidential data. And some clients want even their relationship with you to be confidential, so OP may not be able to share even that. I work for a consulting firm where we don't even name clients to other employees not working with that client. – Kat Sep 17 '20 at 05:05
  • Do the clients have a terminal server or a VM solution? You could RDP to a remote windows host on their LAN and all their files stay on their network. Your laptop becomes a fancy terminal. – Criggie Sep 17 '20 at 07:54
  • Does client X's network block traffic that it can't decrypt? In other words, would you be able to use something like a pre-shared key to encrypt a connection to a remote machine, then do all of your client A/B work on the remote machine? – bta Sep 18 '20 at 00:17
  • If you only get SSL errors on sites that enforce key pinning, does that mean you've accepted their root certificate already and are currently leaking the rest of your HTTPS traffic? – John Laxson Sep 18 '20 at 00:22
  • All the clients involved understand that they are not my only client. I'm not trying to hide the fact that I'm working on other projects, just trying to keep each client's private data private. – duggulous Sep 18 '20 at 18:28
  • 1
    Am I missing it somewhere, or has anyone pointed out that the issue here revolves around using X's resources while working with A and B? The legally correct answer would be "don't do that", right? Regardless of infosec, just keeping track of billable time in this scenario is error-prone. Assuming that can be dealt with, the VM solutions sound like a reasonable compromise, along with e.g. a portable hotspot to bypass network X when on site at X. – stevegt Sep 18 '20 at 20:41
  • I think the only resources of X's that one could argue are being used to the benefit of A and B would be the infrastructure carrying packets bound for A and B across X's network to the internet. Preventing those packets from touching their network is exactly what I'm hoping to accomplish. – duggulous Sep 18 '20 at 21:57

6 Answers6

39

You could use a very small VM for each one, but keep the IDE on the host, not on the guests. Share a folder from the VM to the host, so you use the host and its resources to develop, and use the VM networking to access the client environment.

Most of the VPN software can run on Linux, so you could create a very light Linux guest with 256MB of memory and install only the VPN client and ssh server. To access the environment from the host, use SSH Tunneling to create a proxy (putty, for example, works very well) so you don't need VPN on the host.

ThoriumBR
  • 50,648
  • 13
  • 127
  • 142
  • 19
    For that matter you could just use a docker container, which will likely be even lower on resource usage – Conor Mancone Sep 15 '20 at 23:06
  • 3
    A container would be even better. – ThoriumBR Sep 15 '20 at 23:08
  • 9
    @ConorMancone That depends on how rigorous you need the isolation to be. VMs still beat containers in terms of security by most measures. And of course, for this you don't even need 256MB of RAM per VM unless you're insisting on using distros that refuse to install with less. Linux runs fine down into the double digit MB of RAM range and this is not something you need a lot of memory for. – Austin Hemmelgarn Sep 16 '20 at 13:57
  • 5
    An Alpine installation would run with 32MB and be able to run OpenVPN, or AnyConnect, and sshd, and still have memory to spare... And if the idea is isolating the network, a container is as good as a VM. – ThoriumBR Sep 16 '20 at 14:21
  • @AustinHemmelgarn I don't think the extra isolation would be important in this particular use-case, but that obviously depends on your own preferences! – Conor Mancone Sep 16 '20 at 15:28
  • 2
    Good idea, but I'd take it the other direction and have N completely isolated VMs, one for each customer network. Yes there will be duplication, but there will definitely be isolation. – Criggie Sep 17 '20 at 07:53
  • For convenience, and if fiddling to set it up is not an issue, you can run a reverse proxy on the guest, so you can explicitly access sites (including intranet) on the host through the VPN when needed (e.g. using somesite.com.myvm.local) – Erik A Sep 18 '20 at 11:23
16

If you use a operating system that has support for separate networking namespaces, use that feature to start each VPN client and all applications in a distinct client-namespace.

There are a lot of tutorials how to achieve that with Linux: e.g. this or this and there is also a tag on unix stack exchange.

This approach uses a lot less resources than starting VMs.

Josef
  • 5,903
  • 25
  • 33
7

Enable split tunneling, so the only traffic that goes across the VPN to Client X is traffic bound for their servers.

  • 1
    This assumes you can reliably detect which traffic is directed to each client, and that their internal addressing don't overlap. Plus, it doesn't help with the need of trusting client X root certificate. – Ángel Sep 16 '20 at 00:40
  • 7
    This also might make cross-talks between these networks possible. Even if no explicit traffic can flow the browser can connect to all these networks at the same time and could be used as a trampoline to access one network from the other (i.e. CSRF or similar). – Steffen Ullrich Sep 16 '20 at 03:45
  • I've never set up split tunneling before, but in theory this sounds like it might work. I'll need to explore this more – duggulous Sep 18 '20 at 18:50
6

If you are on a Linux laptop, I recommend a separate Linux user for each client. Those separate users can each have their own scripts to connect to a network and VPN if necessary.

With this method and setting proper permissions, unless you deliberately su to another user you are almost assured to not cross-contaminate. I recommend having another user for your personal use, and yet another folder under /home/ for files that you do intend to access from all Linux users, such as music if you have headphones.

My own /home/ looks like this, and I don't even work in security:

$ ls -l /home
drwxr-x--x  9 dotancohen dotancohen  4096 Mar  6  2020 client_bar
drwxr-x--x  6 dotancohen dotancohen  4096 Mar 29  2019 client_foo
drwxr-xr-x 58 dotancohen dotancohen  4096 Sep 16 11:40 dotancohen
drwx------  2 root       root       16384 Nov 25  2019 lost+found
drwxr-xr-x  7 dotancohen dotancohen  4096 Aug 25 10:04 media

$ ls -l /home/media
total 20
drwxrwxr-x 6 dotancohen dotancohen 4096 Mar 27  2019 audiobooks
drwxrwxr-x 5 dotancohen dotancohen 4096 Jun 18 23:52 books
drwxrwxr-x 2 dotancohen dotancohen 4096 Apr  5  2018 music

Note that the clients' folders require the user to be in the client's group, but my normal user and the media file allow anyone to browse.

dotancohen
  • 3,698
  • 3
  • 24
  • 34
  • 4
    Most VPN clients require root because they change the firewall/routing configuration. So this won't work without different network namespaces, if you ever want to work in parallel. – Josef Sep 16 '20 at 10:54
  • I was not intending for two of these users, nor their network connections, to be used in parallel. But thank you for mentioning how it could be done. The only time I've used Linux namespacing is when it's hidden behind Docker! – dotancohen Sep 16 '20 at 12:17
  • @Josef: Not if you use namespaces properly. :-) – R.. GitHub STOP HELPING ICE Sep 18 '20 at 03:52
4

To add to @ThoriumBR answer above (I'm not allowed to leave comments yet :().

I use a pair of docker containers running the VPN software within each and use SSh tunnelling to access servers on "the other side" of the VPN connection (usually via browser with socks proxy settings). This works quite well, but in your case would be potentially wrong and could allow data crossing. I just thought I'd add this tidbit in case someone else is looking for something like this but not exactly the OP's original problem.

If you don't want to hardcode the credentials, a simple FIFO/Pipe works really well for not storing the user ID and password and still allows for an interactive prompt for the bits of required info. Example from the startup script of the container:

# Copy the ID and password from the pipe that has the startup script on the other end
# and has prompted for the two values. These values will be written to a file that is
# used during openconnect's startup and authentication and then deleted 30 seconds afterwards.
# The OVPN file needs to be updated so that "auth-user-pass" (which prompts to the command 
# line)is updated to be "auth-user-pass /openvpn.pass"
# Use 'mkfifo PASS' in the current directory to create the passthrough and this folder must be shared with the container.
cat /keys/PASS > /openvpn.pass
cat /keys/PASS >> /openvpn.pass
chmod 600 /openvpn.pass
$( sleep 30 ; rm /openvpn.pass ) &

The startup script for the container will have the following ("openconnect" is the container name):

docker start openconnect
read -r -p "UserID:" TFR
echo "$TFR" > PASS
read -r -s -p "Password: " TFR
echo -e "$TFR\e" > PASS

Obviously, data collected from the VPNs can be stored within or external to the docker container, depending on your needs for archival and backup purposes.

If you really want to get creative you could have encrypted folders being the shared data location without needing to encrypt the entire VM/Container.

There's no reason why this shouldn't work on any OS as well.

Edit: As requested, here's the complete script file for the full setup (It may not be perfect, but I only spent an hour on it, so meh! :) ):

#!/bin/bash
# This script will create a dockerfile to then create a docker image and then start it.
# The image will contain this file to be run on startup, making this an all-in-one file
# for a docker image proxy to the vpn. Assumes to be run from your .ssh directory for
# setup.
#
# Options:
#       "dockerfile" - Create the docker file needed to create the proxy container image
#       "container" - Create the container running the proxy and VPN
#       "start" - Start an existing container

if [ $# -gt 0 ] ; then
        if [ "$1" == "dockerfile" ] ; then
                if [ -f opentrust.docker ] ; then
                        rm opentrust.docker
                fi
                shift
        fi
        if [ ! -f opentrust.docker ] ; then
                echo Generating the docker file...
                cat > opentrust.docker <<-EOF
                        FROM openbase

                        RUN useradd -m -s /bin/bash myuser
                        RUN mkdir /home/myuser/.ssh
                        # Copy your SSH key into the image to allow you to SSH in using your normal key
                        COPY id_ecdsa.pub /home/myuser/.ssh/authorized_keys
                        RUN chmod 600 /home/myuser/.ssh/authorized_keys
                        RUN chown -R myuser:myuser /home/myuser/.ssh

                        COPY startTrust.sh /
                        RUN chmod +x /startTrust.sh

                        RUN apt-get install -y openvpn

                        ENTRYPOINT ["/startTrust.sh"]
                        EOF
        else
                echo "opentrust.docker already exists Delete it to regenerate. Using existing file..."
        fi

        if [ "$1" == "container" ] ; then
                docker build -t opentrustimg -f opentrust.docker .
                shift
        fi
        if [ "$1" == "start" ] ; then
                docker start opentrust
                if [ $? -gt 0 ]; then
                        echo "opentrust doesn't exist... creating one"
                        # Container didn't exist, create one and start it. SSH into it via port 24
                        # Container has access to the .ssh folder of your user to read ID/PWD and write log files etc...
                        #docker run -d --privileged --name opentrust -p 24:22 --mount type=bind,source="$(pwd)",target=/keys opentrustimg
                        docker run -d --cap-add=NET_ADMIN --device=/dev/net/tun --name opentrust -p 24:22 --mount type=bind,source="$(pwd)",target=/keys opentrustimg
                fi
                read -r -p "UserID:" TFR
                echo "$TFR" > PASS
                read -r -s -p "Password: " TFR
                echo -e "$TFR\e" > PASS
                echo Waiting for startup...
                sleep 8
                docker logs --tail 100 opentrust
        fi
        docker ps
        exit
fi

set +x
/usr/sbin/sshd -D &
# Copy the ID and password from the pipe that has the startup script on the other end
# and has prompted for the two values. These values will be written to a file that is
# used during opentrust's startup and authentication and then deleted 30 seconds afterwards.
# The OVPN file needs to be updated so that "auth-user-pass" (which prompts to the command 
# line) is updated to be "auth-user-pass /openvpn.pass"
# Use 'mkfifo PASS' in the .ssh directory to create the passthrough.
cat /keys/PASS > /openvpn.pass
cat /keys/PASS >> /openvpn.pass
chmod 600 /openvpn.pass
$( sleep 30 ; rm /openvpn.pass ) &
$( sleep 30 ; echo -e 'nameserver 192.168.120.1\nsearch remote-domain.ca' > /etc/resolv.conf ) &
openvpn --config /keys/myuser@open.vpn.config.ovpn.docker

OOPS. Forgot about how to define "openbase". Here's that script:

#!/bin/bash
# This script will create a dockerfile to then create a docker base image used by the 
# startTrust.sh scripts containing OpenSSH server, Dig, Curl and OpenVPN.
#
# Options:
#       "dockerfile" - Create the docker file needed to create the "openbase" base container image

if [ $# -gt 0 ] ; then
        if [ "$1" == "dockerfile" ] ; then
                if [ -f openBase.docker ] ; then
                        rm openBase.docker
                fi
                shift
        fi
        if [ ! -f openBase.docker ] ; then
                echo Generating the docker file...
                cat > openBase.docker <<-EOF

                        FROM ubuntu

                        RUN mkdir /keys

                        RUN apt-get update
                        RUN apt-get upgrade -y
                        RUN apt-get install -y curl openssh-server
                        RUN apt install -y dnsutils inetutils-ping

                        RUN mkdir /var/run/sshd
                        RUN echo 'root:TH3PASSWoRDYOUCREATED!' | chpasswd
                        RUN sed -i 's/.*PubkeyAuthentication yes/PubkeyAuthentication yes/ ; s/.*AuthorizedKeysFile/AuthorizedKeysFile/ ; s/#GatewayPorts.*/GatewayPorts yes/' /etc/ssh/sshd_config

                        # SSH login fix. Otherwise user is kicked off after login
                        RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

                        ENV NOTVISIBLE "in users profile"
                        RUN echo "export VISIBLE=now" >> /etc/profile

                        RUN useradd -m -s /bin/bash myuser
                        # Don't use this, use SSH keys
                        # RUN echo "myuser:Th3myuserPassw0rd!" | chpasswd 
                        RUN mkdir /home/myuser/.ssh
                        RUN chmod 700 /home/myuser/.ssh
                        # Copy your SSH key into the image to allow you to SSH in using your normal key
                        COPY id_ecdsa.pub /home/myuser/.ssh/authorized_keys
                        RUN chmod 600 /home/myuser/.ssh/authorized_keys
                        RUN chown -R myuser:myuser /home/myuser/.ssh

                        EXPOSE 22
                        EOF
                        # Disable IPv6
                        #cat > /etc/sysctl.d/70-ipv6.conf <-EOF
                        #net.ipv6.conf.all.disable_ipv6 = 1
                        #net.ipv6.conf.default.disable_ipv6 = 1
                        #EOF
                        #nmcli connection modify ens33 ipv6.method ignore ipv4.dns-priority 10 ipv4.dns-search wte93c2a9
                        #nmcli connection modify ens37 ipv6.method ignore ipv4.dns-priority 100 ipv4.dns-search wte93c2a9
                        #EOF
        else
                echo "openBase.docker already exists Delete it to regenerate. Using existing file..."
        fi

        if [ "$1" == "container" ] ; then
                docker build -t openbase -f openBase.docker .
        fi
        # Example container creation command:
        # docker run -d --name openIMAGE -p 24:22 --mount type=bind,source="$(pwd)",target=/keys openIMAGEimg
        docker image ls
        exit
fi
millebi
  • 51
  • 3
  • Any chance you could share details about how you put `openconnect` in a docker container? I'm forced to use `openconnect` for my work and I would love to be able to containerize it and only use it for certain connections. – vikarjramun Oct 13 '20 at 05:07
  • I have updated the original answer with the scripts I use to create the container(s). It's two parts because I use the OpenBase as a core for two containers running two different OpenConnect VPN instances. Don't forget to update any passwords and user IDs ("myuser" should be your user ID). – millebi Oct 14 '20 at 17:29
  • Also note the following page's security hints as they may be relevant in this case: https://cloudberry.engineering/article/dockerfile-security-best-practices/ – millebi Oct 16 '20 at 14:39
0

There are quite a few different types of risk when you connect to some corporate VPN, for both parties. Including, but not limited to:

  • You doing something bad on their network (with or without intent)
  • A malware in your computer doing something bad on their network
  • A vulnerability in your computer used by some third party to do something bad on their network
  • Their VPN client software doing something bad to your computer (I bet you got the software from them and it is them who manage its network settings, not you, it also runs w/ administrative privileges)
  • Their firewall compromising (by logging and disclosing later) your sensitive info
  • A vulnerability in their VPN software or a misconfiguration allowing third party to do something bad on your computer
  • The VPN misconfigured by the corporate IT into using weak (or no at all) encryption and corporate data related to your work leaking. You being accused of leaking it.

etc, etc

That's why connecting to a corporate VPN requires a great deal of trust between both parties.

Some of these reasons are why the usual corporate VPN client is pretty invasive - it intercepts (or stops) the traffic to the Internet. In some cases you lose access to your local network as well.

Connecting to 2 or more corporate networks complexifies the things because you expose both your clients to risks arising from your connection to the other one. Do they have any reason to trust each other?

Depending on the security requirements of your clients (and your own), the solution may range from:

  • do nothing. Use whatever configuration "just works" and hope for the best
  • connect to only one corporate network at a time
  • setup (or hack - you may not be able to setup) VPN clients to route only the traffic related to the corresponding party
  • setup a separate VM for running the VPN client and whatever else you need to contact the corresponding party
  • setup a separate hardware dedicated to working with the corresponding party
  • the above + split teams (dedicated person contacting the network of the corresponding party)

etc, etc

I personally had to do everything of the above in different cases.

Depending on circumstances, it may be a clear breach of your NDA to route information from one client into TLS-decrypting firewall of another one. Including, but not limited to, your own email access.

Some of the above (e.g. hacking the VPN client) may also piss the hell out of some control-obsessed corporate IT (guess where I know from) even if it is the only way you can do your work.

fraxinus
  • 3,425
  • 5
  • 20