├── .dockerignore
├── .gitignore
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.sample.yml
├── docker-compose.testopenvpn.yml
├── sample.env
├── src
├── openvpn.client.expect
├── openvpn.onc.sh
├── openvpn.pki.expect
├── openvpn.sh
├── openvpn_check_password.sh
└── supervisord.config
└── test
├── test.sh
├── test_ca_master_password
└── testclient
├── Dockerfile
└── test_1.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .gitignore
3 | runtime*
4 | test
5 | ca_master_password.txt
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | runtime
2 | .env
3 | ca_master_password.txt
4 | docker-compose.yml
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Build an openvpn server and PKI insfrastructure optimized for use with a
16 | # ChromeOS system.
17 |
18 | FROM kylemanna/openvpn
19 |
20 | RUN apk update && \
21 | apk add supervisor certbot expect util-linux coreutils dnsmasq
22 |
23 | ENV PUBLIC_HOSTNAME=foo.example.com
24 | ENV ADMIN_EMAIL=admin@example.com
25 | ENV CERTBOT_STAGING_FLAG=--staging
26 |
27 | VOLUME /etc/letsencrypt
28 | VOLUME /etc/openvpn
29 | VOLUME /etc/dnsmasq.d
30 |
31 | EXPOSE 443
32 | EXPOSE 1194
33 |
34 | COPY src/openvpn.sh /asacamano/openvpn/openvpn.sh
35 | COPY src/openvpn.pki.expect /asacamano/openvpn/openvpn.pki.expect
36 | COPY src/openvpn.client.expect /asacamano/openvpn/openvpn.client.expect
37 | COPY src/openvpn.onc.sh /asacamano/openvpn/openvpn.onc.sh
38 | COPY src/supervisord.config /asacamano/openvpn/supervisord.config
39 | COPY src/openvpn_check_password.sh /asacamano/openvpn/check_password.sh
40 | ENTRYPOINT ["/asacamano/openvpn/openvpn.sh"]
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2017 Google, Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenVPN server tuned for ChromeOS clients
2 |
3 | ## Overview
4 |
5 | This is an extension of [kylemanna/openvpn](https://hub.docker.com/r/kylemanna/openvpn/) that
6 | includes:
7 |
8 | * tools to make it easy to configure your ChromeOS client to connect to this VPN
9 | * some shortcuts to make initialization automatic
10 | * Let's Encrypt certificates for the VPN server
11 | * an instance of dnsmasq that serves up public DNS in addition to the contents of the containers
12 | `/etc/hosts` and `/etc/dnsmasq.d/extra-hosts`
13 |
14 | ## Motivation
15 |
16 | When trying to develop on a Chromebook, I didn't like three things:
17 |
18 | 1. I find it frustratingly slow to use a full remote desktop solution.
19 | 1. Tools exist for remote development (such as Eclipse Che) but they work best on a private
20 | network.
21 | 1. It it very difficult to do the equivalent of setting a host file on a ChromeOS system.
22 |
23 | So I decided that the best way to accomplish this was to create an Docker image for OpenVPN that I
24 | could run on any server I had access to (a cloud VPN, a headless machine in a bookshelf, etc), that
25 | provided its own DNS service.
26 |
27 | ## Project status
28 |
29 | _This is not an official Google product._
30 |
31 | This is experimental software, not feature complete, not security reviewed, ant not ready to do
32 | anything except be a science experiment.
33 |
34 | ## How to use it
35 |
36 | 1. `cp sample.env .env` and edit it to include the right values for you.
37 | 1. Put your master CA password in ca_master_password.txt - or use another supported method for
38 | managing docker secrets.
39 | 1. Launch the openvpn service:
40 | ```docker-compose up -d openvpn```
41 | 1. Get the client info:
42 | ```docker-compose exec openvpn /asacamano/openvpn/openvpn.sh chromeos_client ```
43 | The client name should be a single word, no spaces or special characters.
44 | 1. Find the `.onc` file that was generated - likely at:
45 | ```$ ls -l ${PWD}/runtime/c:q!etc/openvpn/client-config//${PUBLIC_HOSTNAME}```
46 | Download it onto your chromeos device.
47 | 1. Install the files on chromeos. Open a the [net-internals](chrome://net-internals/#chromeos)
48 | tab, and click `Choose File` under `Import ONC file`.
49 | * If it succeeded, you will see `VPN Disconnected` in the settigns menu.
50 | * If it failed, open the [system](chrome://system) tab, and expand `Profile[0] chrome_user_log`
51 | 1. You need to supply a password to make ChromeOS happy - but it's not used on the server, do it
52 | can be anything you choose.
53 | 1. If you want to specify other "host" file entries - added them to `/etc/dnsmasq.d/extra-hosts`,
54 | observing the standard hosts file syntax `IP name [name...]`
55 |
56 | ## Why
57 |
58 | * kylemanna/openvpn is a popular well-supported general OpenVPN docker image, so I started with it.
59 | * Use Let's Encrypt so that you don't have to add another CA to your client. (If someone hacks
60 | your VPN, and it has a CA that you trust to identify servers, they could hack your VPN to hijack
61 | your connections to anyone else AND present a cert your browser will trust. I don't feel like a
62 | password on the CA key is safe enough, given the risk. Whereas if you use a public CA to issue
63 | the cert for your VPN, the hacker only gets to hack you VPN traffic, but not MITM all of your SSL
64 | connections.)
65 | * Store the password for the CA in a docker secret - since the CA is only used to identify clients,
66 | a hacker with this password can connect to your VPN, which they can do with root access to the
67 | VPN host anyway.
68 | * I set some default configuration to make it possible to send all traffic to the VPN so that one
69 | doesn't need to do extensive configuration to handle whatever IPs are behind the VPN - anything
70 | the VPN server can see, the clients can see.
71 | * TODO: Since certbot needs to use port 443 (or another on a short list of popular ports) there needs to
72 | be some way to proxy traffic from this service port 443 to whatever the end user acutally wants
73 | to be listening on port 443 - so we need haproxy (ngxin, apache, monkey, lighthttpd etc don't
74 | proxy SSL wihtout termination)
75 | * TODO: Since chromeos doesn't support scp, the client needs a quick and simple way to get a .onc file,
76 | which is monkey.
77 |
78 | ## How it works
79 |
80 | * It wraps kylemanna/openvpn with some resonable defaults.
81 | * This docker images uses [expect](http://expect.sourceforge.net/) to automate some of the manual
82 | setup tasks in the base image.
83 |
84 | ## Debugging
85 |
86 | * open-vpn options: --verb 6 or verb 6
87 | * `netcat -ul 1194` on the server, `nc -4u -q1 1.2.3.4 1194` on the client to see what's happening.
88 |
89 | ## Roadmap
90 |
91 | TODO:
92 | * run cron in supervisord
93 | * add a cron job to look for changes to the certs, and hup the VPN server when they change
94 | * add a cron job to refresh certbot certs daily
95 |
--------------------------------------------------------------------------------
/docker-compose.sample.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # This docker compose file will set up an OpenVPN image that an be used with certbot
16 |
17 | version: '3.1'
18 |
19 | secrets:
20 | ca_master_password:
21 | file: ca_master_password.txt
22 |
23 | services:
24 | openvpn:
25 | image: asacamano/openvpn
26 | restart: always
27 | cap_add:
28 | - NET_ADMIN
29 | container_name: openvpn
30 | ports:
31 | - "1194:1194/udp"
32 | - "443:443/tcp"
33 | volumes:
34 | - ./runtime/etc/openvpn:/etc/openvpn
35 | - ./runtime/etc/letsencrypt:/etc/letsencrypt
36 | environment:
37 | - ADMIN_EMAIL=[YOUR EMAIL HERE - for Let's Encrypt]
38 | - PUBLIC_HOSTNAME=[YOUR HOSTNAME HERE]
39 | # Change this to staging to test Let's Encrypt
40 | - CERTBOT_STAGING_FLAG=staging
41 | secrets:
42 | - ca_master_password
43 | # Add your services here
44 |
--------------------------------------------------------------------------------
/docker-compose.testopenvpn.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # This docker compose file will set up an OpenVPN image that an be used with certbot
16 |
17 | version: '3.1'
18 |
19 | secrets:
20 | ca_master_password:
21 | file: ca_master_password.txt
22 |
23 | networks:
24 | private:
25 | driver: bridge
26 | ipam:
27 | config:
28 | - subnet: 10.5.0.0/24
29 | public:
30 | driver: bridge
31 | ipam:
32 | config:
33 | - subnet: 10.6.0.0/24
34 |
35 | services:
36 | openvpn:
37 | image: asacamano/openvpn
38 | build: .
39 | cap_add:
40 | - NET_ADMIN
41 | container_name: openvpn
42 | ports:
43 | - "1194:1194/udp"
44 | - "443:443/tcp"
45 | volumes:
46 | - ./runtime/etc/openvpn:/etc/openvpn
47 | - ./runtime/etc/letsencrypt:/etc/letsencrypt
48 | networks:
49 | private:
50 | ipv4_address: 10.5.0.2
51 | public:
52 | ipv4_address: 10.6.0.2
53 | environment:
54 | - ADMIN_EMAIL
55 | - PUBLIC_HOSTNAME
56 | - CERTBOT_STAGING_FLAG
57 | secrets:
58 | - ca_master_password
59 | testserver:
60 | image: nginx:alpine
61 | networks:
62 | private:
63 | ipv4_address: 10.5.0.3
64 |
--------------------------------------------------------------------------------
/sample.env:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | #
16 | # Sample environment variables file for asacamano/openvpn
17 | #
18 |
19 | # Common
20 | ADMIN_EMAIL=
21 | PUBLIC_HOSTNAME=
22 |
23 | # Certbot
24 |
25 | # Use the staging server unless this line is explicitly set and empty (or set to a valid flag
26 | # unrelated to staging)
27 | # For real certs:
28 | # CERTBOT_STAGING_FLAG=
29 | # For testing
30 | CERTBOT_STAGING_FLAG=--staging
31 |
--------------------------------------------------------------------------------
/src/openvpn.client.expect:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | #
16 | # Set up a single OpenVPN client
17 | #
18 |
19 | set clientname [lindex $argv 0];
20 |
21 | spawn easyrsa build-client-full "$clientname" nopass
22 |
23 | # Now sign the default cert - needs password again
24 | expect "Enter pass phrase for /etc/openvpn/pki/private/ca.key:"
25 | sleep 1
26 | send "$env(OPENVPN_CA_PASSWORD)\r"
27 |
28 | #expect "Data Base Updated"
29 | expect EOF
30 |
--------------------------------------------------------------------------------
/src/openvpn.onc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2017 Google Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # TODO: High-level file comment.
18 | #!/bin/bash
19 |
20 | CLIENT_NAME=${1-""}
21 | USERNAME=${CLIENT_NAME}
22 | GUID1=$( uuidgen )
23 | GUID2=$( uuidgen )
24 | GUID3=$( uuidgen )
25 | CACERT=$( cat /etc/openvpn/pki/ca.crt | tail -n +2 | head -n -1 | tr '\n' '*' | sed -e 's/\*//g' )
26 | TA_KEY=$( cat /etc/openvpn/pki/ta.key | grep -v '#' | tr '\n' '*' | sed -e 's/\*/\\n/g' )
27 | CLIENTCERT=$( openssl pkcs12 -export -password 'pass:' -inkey /etc/openvpn/pki/private/${CLIENT_NAME}.key -in /etc/openvpn/pki/issued/${CLIENT_NAME}.crt | base64 -w 0 )
28 |
29 | cat < /etc/openvpn/client-config/${2}/${PUBLIC_HOSTNAME}.onc
42 | echo
43 | echo "Client config in /etc/openvpn/client-config/${2}/${PUBLIC_HOSTNAME}.onc"
44 | echo
45 | cat /etc/openvpn/client-config/${2}/${PUBLIC_HOSTNAME}.onc
46 | exit 0
47 | else
48 | set +euo pipefail
49 | exec "$@"
50 | fi
51 | fi
52 |
53 | # Log the commands and the output
54 | set -x
55 | if [[ ${CERTBOT_STAGING_FLAG-'--staging'} == "--staging" ]]; then
56 | CERTBOT_CONFIG=/etc/letsencrypt/staging
57 | else
58 | CERTBOT_CONFIG=/etc/letsencrypt
59 | fi
60 |
61 | if [[ -f /etc/openvpn/setup-done ]]; then
62 | echo "Using existing setup - checking for cert renewal"
63 | certbot renew --config-dir $CERTBOT_CONFIG
64 | else
65 | echo "Running first-time setup"
66 | # Set up the cert and keys
67 | certbot certonly --standalone --non-interactive --config-dir $CERTBOT_CONFIG --agree-tos ${CERTBOT_STAGING_FLAG-'--staging'} --email ${ADMIN_EMAIL} -d ${PUBLIC_HOSTNAME}
68 |
69 | if [[ ${CERTBOT_STAGING_FLAG-'--staging'} == "--staging" ]]; then
70 | echo "Certboth staging finished. Run with CERTBOT_STAGING_FLAG= to complete setup"
71 | exit 0
72 | fi
73 |
74 | # Set up openvpn
75 | # See https://github.com/kylemanna/docker-openvpn
76 | # and https://github.com/kylemanna/docker-openvpn/blob/master/bin/ovpn_genconfig
77 | # Some other options to consider making exposed via ENV vars:
78 | # Username / password verification
79 | # -e "auth-user-pass-verify /asacamano/openvpn/openvpn_check_pasword.sh via-file" -e "tmp-dir /dev/shm" -e "script-security 2"
80 | # Verbose logging
81 | # -e "verb 6"
82 | ovpn_genconfig -u udp://${PUBLIC_HOSTNAME} -N -z -s 10.8.0.0/24 -n 10.8.0.1
83 |
84 | # Run ovpn_initpki with some scripted values
85 | expect -f /asacamano/openvpn/openvpn.pki.expect
86 |
87 | # Now update openvpn to use the certbot cert to identify itself
88 | mv /etc/openvpn/pki/private/${PUBLIC_HOSTNAME}.key /etc/openvpn/pki/private/${PUBLIC_HOSTNAME}.key.localca
89 | ln -s ${CERTBOT_CONFIG}/live/${PUBLIC_HOSTNAME}/privkey.pem /etc/openvpn/pki/private/${PUBLIC_HOSTNAME}.key
90 | mv /etc/openvpn/pki/issued/${PUBLIC_HOSTNAME}.crt /etc/openvpn/pki/issued/${PUBLIC_HOSTNAME}.crt.localca
91 | ln -s ${CERTBOT_CONFIG}/live/${PUBLIC_HOSTNAME}/fullchain.pem /etc/openvpn/pki/issued/${PUBLIC_HOSTNAME}.crt
92 |
93 | set +x
94 | touch /etc/openvpn/setup-done
95 | fi
96 |
97 | set +euo pipefail
98 | echo exec supervisord -c /asacamano/openvpn/supervisord.config
99 | exec supervisord -c /asacamano/openvpn/supervisord.config
100 |
--------------------------------------------------------------------------------
/src/openvpn_check_password.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2017 Google Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # A simple script that could be expanded to allow password verification
18 | # during VPN connections.
19 |
20 | # exit code of 0 means OK
21 | # exit code of 1 means not OK
22 | # All passwords are OK now
23 | echo "ok"
24 |
--------------------------------------------------------------------------------
/src/supervisord.config:
--------------------------------------------------------------------------------
1 | ; Copyright 2017 Google Inc.
2 | ;
3 | ; Licensed under the Apache License, Version 2.0 (the "License");
4 | ; you may not use this file except in compliance with the License.
5 | ; You may obtain a copy of the License at
6 | ;
7 | ; http://www.apache.org/licenses/LICENSE-2.0
8 | ;
9 | ; Unless required by applicable law or agreed to in writing, software
10 | ; distributed under the License is distributed on an "AS IS" BASIS,
11 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | ; See the License for the specific language governing permissions and
13 | ; limitations under the License.
14 |
15 | ;
16 | ; Configure the OpenVPN and any other jobs required to keep it healthy (such as
17 | ; certbot, etc.)
18 | ;
19 |
20 | [supervisord]
21 | nodaemon=true
22 |
23 | [program:openvpn]
24 | command=/usr/local/bin/ovpn_run
25 | stdout_logfile=/dev/stdout
26 | stdout_logfile_maxbytes=0
27 | stderr_logfile=/dev/stderr
28 | stderr_logfile_maxbytes=0
29 |
30 | [program:dnsmasq]
31 | command=dnsmasq --keep-in-foreground --log-facility=- --conf-file= --conf-dir= --max-ttl=1 --addn-hosts=/etc/dnsmasq.d/extra-hosts
32 | stdout_logfile=/dev/stdout
33 | stdout_logfile_maxbytes=0
34 | stderr_logfile=/dev/stderr
35 | stderr_logfile_maxbytes=0
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2017 Google Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # TODO: High-level file comment.
18 | #!/bin/bash
19 |
20 | # Setup strict mode to make life easy
21 | # See http://redsymbol.net/articles/unofficial-bash-strict-mode/
22 | set -euo pipefail
23 | IFS=$'\n\t'
24 |
25 | echo
26 | echo Cleaning up from old runs
27 | echo
28 |
29 | sudo mkdir -p runtime/etc/openvpn
30 | sudo mkdir -p runtime/etc/letsencrypt
31 | sudo mkdir -p runtime/etc/testclient
32 | sudo rm -Rf \
33 | runtime/etc/openvpn/pki/issued/testclient.crt \
34 | runtime/etc/openvpn/pki/reqs/testclient.req \
35 | runtime/etc/openvpn/pki/private/testclient.key \
36 | runtime/etc/openvpn/client-config/testclient \
37 | runtime/etc/openvpn/client-config/testclient/testclient.pkcs12 \
38 | runtime/testclient.ovpn
39 |
40 | echo
41 | echo Initializing openvpn
42 | echo
43 |
44 | docker-compose up -d
45 | # Wait for openvpn to be available
46 | sh -c 'docker-compose logs -f openvpn | { sed "/success: openvpn entered RUNNING state/ q" && kill $$ ;}' || echo "OK"
47 |
48 | # Allow multiple certs with the same name
49 | sudo sh -c 'echo "unique_subject = no" > runtime/etc/openvpn/pki/index.txt.attr'
50 |
51 | echo
52 | echo Building a client
53 | echo
54 |
55 | docker-compose exec openvpn /asacamano/openvpn/openvpn.sh chromeos_client testclient testuser
56 | docker-compose exec openvpn ovpn_getclient testclient | sudo sh -c 'cat > ./runtime/testclient/testclient.ovpn'
57 |
58 | echo
59 | echo Testing the client
60 | echo
61 |
62 | docker-compose run --rm testclient ./test_1.sh
63 |
64 |
--------------------------------------------------------------------------------
/test/test_ca_master_password:
--------------------------------------------------------------------------------
1 | testpassword
2 |
--------------------------------------------------------------------------------
/test/testclient/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2017 Google Inc.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # A test VPN client that makes sure the server works
16 |
17 | FROM alpine
18 |
19 | RUN apk update && apk add openvpn bash
20 |
21 | ENV TEST_USERNAME=testuser
22 | ENV TEST_PASSWORD=testpassword
23 |
24 | # PUT .ovpn file in /testclient/testclient.ovpn
25 | VOLUME /testclient
26 |
27 | COPY test_1.sh /test_1.sh
28 |
--------------------------------------------------------------------------------
/test/testclient/test_1.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eu
2 | #
3 | # Copyright 2017 Google Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Run a test to make sure that who setup still works.
18 |
19 | set -x
20 |
21 | echo calling the testserver without the VPN
22 | results=$(wget -T 5 -O - 10.5.0.3:80)
23 |
24 | if [[ $? != 0 ]]; then
25 | echo SUCCESS
26 | else
27 | echo FAILURE - the server in the private network should not be visible yet
28 | exit 1
29 | fi
30 | echo Starting openvpn
31 | echo $TEST_USERNAME > /testclient/testclient.auth
32 | echo $TEST_PASSWORD >> /testclient/testclient.auth
33 | /usr/sbin/openvpn --config /testclient/testclient.ovpn --auth-user-pass /testclient/testclient.auth &
34 |
35 | echo waiting
36 | sleep 5
37 |
38 | echo calling the testserver
39 | results=$(wget -T 5 -O - 10.5.0.3:80)
40 |
41 | if [[ $? == 0 ]]; then
42 | echo SUCCESS
43 | else
44 | echo FAILURE - could not connect to the private server over the VPN
45 | exit 1
46 | fi
47 |
--------------------------------------------------------------------------------