Skip to content

Commit 311b6c3

Browse files
committed
Initial Remote Working ForticlientVPN Container
0 parents  commit 311b6c3

File tree

8 files changed

+336
-0
lines changed

8 files changed

+336
-0
lines changed

Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
FROM centos:7
2+
MAINTAINER R. Amosa <[email protected]>
3+
4+
RUN \
5+
yum -y update && yum -y install epel-release && \
6+
yum -y install openssl openssh-clients openssh-server && \
7+
yum -y install bind-utils net-utils ppp pptp curl wget git which less \
8+
vim expect ansible python-pip bash-completion net-tools zip unzip && \
9+
yum -y clean all && \
10+
touch /run/utmp && \
11+
echo "root:root" | chpasswd
12+
13+
RUN \
14+
useradd loginid && \
15+
mkdir ~loginid/.ssh && \
16+
echo "loginid:loginid" | chpasswd
17+
18+
ADD ["bin/forticlientsslvpn.xz", "/usr/local/bin"]
19+
COPY ["bin/forticlientvpn.sh", "/usr/bin"]
20+
21+
COPY ["keys", "/home/loginid/.ssh"]
22+
COPY ["conf/ssh.config", "/home/loginid/.ssh/config"]
23+
COPY ["conf/bash_aliases", "/home/loginid/.alias"]
24+
25+
RUN echo " . ~/.alias " >> /home/loginid/.bashrc
26+
27+
RUN chown -R loginid:loginid /home/loginid/.ssh
28+
RUN chmod -R 600 /home/loginid/.ssh/*
29+
RUN chown loginid:loginid /home/loginid/.alias
30+
31+
RUN /usr/local/bin/forticlientsslvpn/64bit/helper/setup.linux.sh
32+
33+
COPY ["entrypoint.sh", "/"]
34+
35+
RUN chmod 755 /entrypoint.sh
36+
RUN chmod 755 /usr/bin/forticlientvpn.sh
37+
38+
EXPOSE 22
39+
ENTRYPOINT ["/entrypoint.sh"]

README.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Docker Work VPN Container
2+
3+
I needed a really simple enclosed and fully functional work environment that wasn't on my work laptop so I could do work on another station, without having to mess that environment up with work stuff. And it needed to set my work VPN up without my input.
4+
5+
So Docker was of course the logical choice.
6+
7+
## Pre-requisites
8+
9+
* Docker installed
10+
* your work ssh-keys
11+
* your office AD login details
12+
* copy of Fortinet Linux ssl cli client (see below for link) packed in a .xz file
13+
14+
## Objectives
15+
16+
what did I want my work container to do?
17+
18+
* fire up and connect the work Fortinet VPN client with no user input.
19+
* have my authorised ssh-keys set up for all work environments I needed to be able to access
20+
* have my bash alises loaded (cos I like convenience)
21+
22+
## Dockerfile
23+
24+
I'm going to go through each block and try and explain what's happening. I'll have a link at the end with all the files in full so you can skip to that to see everything in its' entirety.
25+
26+
So, what's it doing?
27+
28+
- sets up base image and installs desired packages (add as needed).
29+
- install PPP & PPTP packages are a must for VPN to work.
30+
- sets up 'utmp' and 'root' user, sets password
31+
32+
```ruby
33+
FROM centos:7
34+
35+
RUN \
36+
yum -y update && yum -y install epel-release && \
37+
yum -y install openssl openssh-clients openssh-server && \
38+
yum -y install bind-utils net-utils ppp pptp curl wget git which less \
39+
vim expect ansible python-pip bash-completion net-tools zip unzip && \
40+
yum -y clean all && \
41+
touch /run/utmp && \
42+
echo "root:root" | chpasswd
43+
```
44+
45+
Next
46+
- it creates a (work) user
47+
- creates our .ssh directory and
48+
- sets the user's passwd (loginid = your AD login at the office)
49+
50+
```ruby
51+
RUN \
52+
useradd loginid && \
53+
mkdir ~loginid/.ssh && \
54+
echo "loginid:loginid" | chpasswd
55+
```
56+
57+
Next it's adding our vpn client package, and copying the vpn runtime script.
58+
59+
When you add this (or any package for that matter of this type) .xz file, Docker will automagically unpack the contents in your destination directory (in this case /usr/local/bin):
60+
61+
```ruby
62+
ADD ["bin/forticlientsslvpn.xz", "/usr/local/bin"]
63+
COPY ["bin/forticlientvpn.sh", "/usr/bin"]
64+
```
65+
66+
Then, copy ALL my keys and my ssh config file to $HOME/.ssh:
67+
68+
```ruby
69+
COPY ["keys", "/home/loginid/.ssh"]
70+
COPY ["conf/ssh.config", "/home/loginid/.ssh/config"]
71+
```
72+
73+
Also copy my bash aliases to ~/.alias, and add a line to my ~/.bashrc so that it automagically sources my aliases everytime I login
74+
75+
```ruby
76+
COPY ["conf/bash_aliases", "/home/loginid/.alias"]
77+
RUN echo " . ~/.alias " >> /home/loginid/.bashrc
78+
```
79+
80+
set the right owners and permissions or my keys wont work
81+
82+
```ruby
83+
RUN chown -R loginid:loginid /home/loginid/.ssh
84+
RUN chmod -R 600 /home/loginid/.ssh/*
85+
RUN chown loginid:loginid /home/loginid/.alias
86+
```
87+
88+
Next, this script is needed by forticlient to inialise and accept the license:
89+
90+
```ruby
91+
RUN /usr/local/bin/forticlientsslvpn/64bit/helper/setup.linux.sh
92+
```
93+
94+
- copy our entrypoint.sh (see further down for setting this script up)
95+
- and chmod 755 entrypoint and forticlientvpn** scripts:
96+
97+
```ruby
98+
COPY ["entrypoint.sh", "/"]
99+
RUN chmod 755 /entrypoint.sh
100+
RUN chmod 755 /usr/bin/forticlientvpn.sh
101+
```
102+
103+
That's it.
104+
105+
Next, we have to prep the forticlient setup so that it doesn't have to wait for us to input anything and it just goes ahead and
106+
107+
1. installs without us needing to accept the license
108+
2. runs without us needing to type 'Y' to start the VPN tunnel
109+
110+
## Setting up the forticlient SSL VPN
111+
112+
When you first download the forticlient package on Linux and run it, you'll get an error saying you need to run the following script:
113+
114+
`/usr/local/bin/forticlientsslvpn/64bit/helper/setup.linux.sh`
115+
116+
and this will show you the license you have to scroll through and accept the license.
117+
118+
This is a problem if you just want the container to fire up, set itself up and run without any user input. So we need to remove this section of the script before we can run the container successfully
119+
120+
### Remove Section from 'setup.linux.sh'
121+
122+
This section is the one where you need to scroll through the 'more' output to the bottom, and say 'yes' or whatever to get it to go to the next step. We don't want to do this, we want things to work automagically.
123+
124+
So, remove this section from the script:
125+
126+
```ruby
127+
...
128+
129+
if [ "$1" != "2" ]; then
130+
echo "begin setup at $base..." >> "$inlog"
131+
more "$base/License.txt"
132+
echo -n "Do you agree with this license ?[Yes/No]"
133+
read ans
134+
yn=`echo $ans|sed '
135+
s/y/Y/
136+
s/e/E/
137+
s/s/S/
138+
'`
139+
if [ "$yn" != "YES" -a "$yn" != "Y" ]; then
140+
touch "$base/.nolicense"
141+
chmod a+w "$base/.nolicense"
142+
echo "Do not agree with this license, aborting..."
143+
exit 0
144+
fi
145+
fi
146+
...
147+
```
148+
Just delete everything in this 'if' statement. Save your file. It's done.
149+
150+
### forticlient expect script
151+
For the 2nd part, every time you fire up forticlient vpn it asks you if you want to start the VPN tunnel. Yes. Yes you do. and No, no you don't want to have to type 'Y' every time.
152+
153+
So, we want our entrypoint for the container to be an 'expect' bash script that answers that question for us. Big thanks and full credit for script goes to [mgeeky/github.com](https://gist.github.com/mgeeky/8afc0e32b8b97fd6f96fce6098615a93).
154+
155+
Just include your own VPN details and save this as 'entrypoint.sh'
156+
157+
```ruby
158+
#!/usr/bin/env bash
159+
160+
FORTICLIENT_PATH="/usr/local/bin/forticlientsslvpn/64bit/forticlientsslvpn_cli"
161+
VPN_HOST="host:port"
162+
VPN_USER=""
163+
VPN_PASS=""
164+
```
165+
166+
Right, time to build our image.
167+
168+
## Build Work VPN Container Image
169+
170+
(make sure you're in the same folder as your Dockerfile file)
171+
172+
```ruby
173+
$ docker build --rm -t companyname/vpn:centos7 .
174+
```
175+
176+
## Run it!
177+
178+
Run the container, then 'exec' into it and you should find it connects to your work VPN and is ready for you to remote to all your work environments (well, mine anyway).
179+
180+
_note: you need to run container as 'privileged' for pppd kernel support
181+
the vpn inside docker would complain about kernel not supporting pppd if you don't run privileged._
182+
183+
```ruby
184+
$ docker run -dP --name=workvpn --privileged companyname/vpn:centos7
185+
$ docker exec -u loginid -ti <name_of_container> /bin/bash
186+
```
187+
188+
189+
## Example of output success
190+
191+
Run `$ docker logs <name_of_container>` and see if you can see the following
192+
193+
```ruby
194+
cloudbuilder@hx0:~/vpn $ docker logs workvpn
195+
Killing previous instances of Forticlient SSL VPN client...
196+
spawn /usr/local/bin/forticlientsslvpn/64bit/forticlientsslvpn_cli --server remote.site.com:443 --vpnuser loginid --keepalive
197+
Password for VPN:
198+
STATUS::Setting up the tunnel
199+
STATUS::Connecting...
200+
Certificate:Certificate:
201+
Data:
202+
Version: 3 (0x2)
203+
Serial Number:
204+
205+
206+
...
207+
... //certificate output
208+
... //certificate output
209+
... //certificate output
210+
...
211+
212+
The certificate for the SSLVPN server is invalid.
213+
You are connecting to an untrusted server. which could put your confidential information at risk.
214+
Would you like to connect to this server? (Y/N)
215+
Y
216+
STATUS::Login succeed
217+
STATUS::Starting PPPd
218+
STATUS::Initializing tunnel
219+
STATUS::Connecting to server
220+
STATUS::Connected
221+
Press Ctrl-C to quit
222+
STATUS::Tunnel running
223+
```
224+
225+
When you see 'Tunnel running' you should be good to go!
226+
227+

bin/forticlientsslvpn.xz

3.91 MB
Binary file not shown.

bin/forticlientvpn.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
3+
FORTICLIENT_PATH="/usr/local/bin/forticlientsslvpn/64bit/forticlientsslvpn_cli"
4+
5+
# VPN Credentials
6+
VPN_HOST="YOUR-VPN-PROVIDER-DOMAIN:443"
7+
VPN_USER="YOUR-VPN-USERNAME"
8+
VPN_PASS="YOUR-VPN-PASSWD"
9+
10+
# --------------------------------------------
11+
12+
trap ctrl_c INT
13+
14+
function ctrl_c() {
15+
echo "Removing left-over files..."
16+
rm -f /tmp/expect
17+
}
18+
19+
if [[ $EUID -ne 0 ]]; then
20+
echo "This script must be run as root"
21+
exit 1
22+
fi
23+
24+
if [ -z "$FORTICLIENT_PATH" ]; then
25+
FORTICLIENT_PATH=`uname -r | grep -q 64 && echo $(locate forticlientsslvpn_cli | grep 64bit) || echo $(locate forticlientsslvpn_cli | grep 32bit)`
26+
if [ ! -f $FORTICLIENT_PATH ]; then
27+
echo "Tried to locate Forticlient SSL VPN Cli binary, but failed."
28+
echo "Specify it at variable FORTCLIENT_PATH"
29+
exit 1
30+
fi
31+
echo "Located Forticlient VPN Client at: $FORTICLIENT_PATH"
32+
fi
33+
34+
echo "Killing previous instances of Forticlient SSL VPN client..."
35+
killall -9 $(basename $FORTICLIENT_PATH) 2> /dev/null
36+
37+
cat << EOF > /tmp/expect
38+
#!/usr/bin/expect -f
39+
match_max 1000000
40+
set timeout -1
41+
spawn $FORTICLIENT_PATH --server $VPN_HOST --vpnuser $VPN_USER --keepalive
42+
expect "Password for VPN:"
43+
send -- "$VPN_PASS"
44+
send -- "\r"
45+
46+
expect "Would you like to connect to this server? (Y/N)"
47+
send -- "Y"
48+
send -- "\r"
49+
50+
expect "Clean up..."
51+
close
52+
EOF
53+
54+
chmod 500 /tmp/expect
55+
/usr/bin/expect -f /tmp/expect
56+
57+
rm -f /tmp/expect

conf/bash_aliases

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# aliases file

conf/ssh.config

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# EDIT THIS AS NEEDED!
2+
3+
Host *
4+
User loginid
5+
IdentityFile ~/.ssh/loginid_id_rsa

entrypoint.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
3+
# fire up the VPN
4+
exec /usr/bin/forticlientvpn.sh

keys/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Keys
2+
3+
usual ~/.ssh/ keys - and other keys you want copied into your container, go here.

0 commit comments

Comments
 (0)