diff --git a/CHANGELOG.md b/CHANGELOG.md index 527535e..00ec534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +### 2.0.0 - Partial rewrite + +- Moved `/config/hooks` to `/config/openvpn/hooks` +- Renamed `/config/openvpn/server` to `config` +- Changed base image to [slocomptech/baseimage-alpine](https://github.com/SloCompTech/docker-baseimage-alpine) +- Moved all helper scripts to `/root/usr/local/bin` +- Got rid of bash lib files +- Hiearhicaly moved all commands under the hood of `ovpn` command +- Improved backup command +- Added restore command +- Changed base image +- Added **armhf** build + ### 1.0.6 - Bugfix - Added missing `DNS` keyword to **dhcp-option** in example configs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d065d30..2668afd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,76 +6,70 @@ Feel free to contribute to this project. Sections: -- [Example configs & hooks](root/defaults/example/README.md) +- [Example configs & hooks](root/defaults/example/README.md) - [Guides](docs/README.md) - [Helper Scripts](root/app/README.md) - [Modules](root/defaults/module/README.md) ## Syntax -- Identation: tab (4 spaces width) +- Identation: space (2 spaces width) - Javadoc style documentation ## Directory structure of project ``` -/app # Utils (part of image) - bin # Scripts for using this image /config # Configuration dir (all config is here, generated on container start) - openvpn # Openvpn configuration - ccd # Client config directory - client # Client configuration directory - .conf # Base for building client config (all files merged) - server # Server configuration directory - .conf # Server config files (all files merged) - pki - ca.crt # CA certificate - certs by serial # Certs by Serial ID - .pem - crl.pem # CRL - dh.pem - index.txt # Database index file - issued - .crt # Certificates - private # Directory with private keys - ca.key # CA secret - .key # Certificate secrets - reqs # Directroy with signing requests - serial # The current serial number - ta.key # Secret for tls-auth, tls-crypt - ssl - safessl-easyrsa.cnf - vars - example # Example configs (see root/defaults/example/README.md) - config # Example client & server configs - hook # Example hook configs - module # Modules for openvpn + backup # Folder where backups are generated + example # Example configs (see root/defaults/example/README.md) + module # Modules for openvpn + openvpn # Openvpn configuration + ccd # OpenVPN client-specific configuration directory (applied when client connects) + client # Client configuration directory (for generation of .ovpn files) + .conf # Base for building client config (all files merged) + config # Running config (server/client) + .conf # Config files (all files merged) hooks # Put your custom scripts in one of subfolders - auth # On authentication (needs to be enabled in config) - client-connect # Client connected - client-disconnect # Client disconnected - down # After interface is down - finish # Deinit container - init # Init container - learn-address - route-up # After routes are added - route-pre-down # Before routes are removed - up # After interface is up - tls-verify # Check certificate + auth # On authentication (needs to be enabled in config) + client-connect # Client connected + client-disconnect # Client disconnected + down # After interface is down + finish # Deinit container + init # Init container + learn-address + route-up # After routes are added + route-pre-down # Before routes are removed + up # After interface is up + tls-verify # Check certificate system.conf # System OpenVPN config file (do not edit, unless instructed) - include-server.conf # File that includes all server configuration files (automatically generated) - donotdelete # Leave this file alone, if deleted it triggers full setup + include-conf.conf # File that includes all configuration files (automatically generated) + pki + ca.crt # CA certificate + certs by serial # Certs by Serial ID + .pem + crl.pem # CRL + dh.pem + index.txt # Database index file + issued + .crt # Certificates + private # Directory with private keys + ca.key # CA secret + .key # Certificate secrets + reqs # Directroy with signing requests + secret.key # Static key (if not using real PKI) + serial # The current serial number + ta.key # Secret for tls-auth, tls-crypt + ssl + safessl-easyrsa.cnf + vars + tmp # Temporary folder /defaults # Default configuration, which is copied into config on full setup - example # Examples - config # Example configs - hook # Example hooks - module # Modules (for example password authentication ...) - system.conf # Original server config + ... /etc # System config - cont-init.d # Scripts run before services are started - fix-attrs.d # Fix file permissions - logrotate.d # Log settings - services.d # Scripts that start services + cont-init.d # Scripts run before services are started + cont-finish.d # Scripts run after services are finished + fix-attrs.d # Fix file permissions + services.d # Scripts that start services ``` ## Useful links @@ -92,4 +86,4 @@ Sections: - [OpenVPN docs](https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN) - [Setup OpenVPN on alpine linux](https://wiki.alpinelinux.org/wiki/Setting_up_a_OpenVPN_server#Alternative_Certificate_Method) - [EasyRSA](https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN) -- [EasyRSA doc](https://github.com/OpenVPN/easy-rsa/tree/master/doc) \ No newline at end of file +- [EasyRSA doc](https://github.com/OpenVPN/easy-rsa/tree/master/doc) diff --git a/Dockerfile b/Dockerfile index 6211e01..f81ef80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,8 @@ # # Base image -# @see https://github.com/linuxserver/docker-baseimage-alpine -# @see https://github.com/linuxserver/docker-baseimage-alpine-python3 +# @see https://github.com/SloCompTech/docker-baseimage # -FROM lsiobase/alpine.python3:latest +FROM slocomptech/baseimage:alpine # Build arguments ARG BUILD_DATE @@ -17,61 +16,73 @@ ARG VERSION # @see http://label-schema.org/rc1/ # @see https://semver.org/ # -LABEL org.opencontainers.image.title="OpenVPN Server" \ - org.label-schema.name="OpenVPN Server" \ - org.opencontainers.image.description="Docker image with OpenVPN server" \ - org.label-schema.description="Docker image with OpenVPN server" \ - org.opencontainers.image.url="https://github.com/SloCompTech/docker-openvpn" \ - org.label-schema.url="https://github.com/SloCompTech/docker-openvpn" \ - org.opencontainers.image.authors="Martin Dagarin " \ - org.opencontainers.image.version=$VERSION \ - org.label-schema.version=$VERSION \ - org.opencontainers.image.revision=$VCS_REF \ - org.label-schema.vcs-ref=$VCS_REF \ - org.opencontainers.image.source=$VCS_SRC \ - org.label-schema.vcs-url=$VCS_SRC \ - org.opencontainers.image.created=$BUILD_DATE \ - org.label-schema.build-date=$BUILD_DATE \ - org.label-schema.schema-version="1.0" +LABEL org.opencontainers.image.title="OpenVPN Server" \ + org.label-schema.name="OpenVPN Server" \ + org.opencontainers.image.description="Docker image with OpenVPN server" \ + org.label-schema.description="Docker image with OpenVPN server" \ + org.opencontainers.image.url="https://github.com/SloCompTech/docker-openvpn" \ + org.label-schema.url="https://github.com/SloCompTech/docker-openvpn" \ + org.opencontainers.image.authors="Martin Dagarin " \ + org.opencontainers.image.version=$VERSION \ + org.label-schema.version=$VERSION \ + org.opencontainers.image.revision=$VCS_REF \ + org.label-schema.vcs-ref=$VCS_REF \ + org.opencontainers.image.source=$VCS_SRC \ + org.label-schema.vcs-url=$VCS_SRC \ + org.opencontainers.image.created=$BUILD_DATE \ + org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.schema-version="1.0" # # Environment variables # @see https://github.com/OpenVPN/easy-rsa/blob/master/doc/EasyRSA-Advanced.md # -ENV PATH="/app/bin:$PATH" \ - S6_BEHAVIOUR_IF_STAGE2_FAILS=0 \ - EASYRSA=/usr/share/easy-rsa \ +ENV EASYRSA=/usr/share/easy-rsa \ EASYRSA_PKI=/config/pki \ EASYRSA_VARS_FILE=/config/ssl/vars \ #EASYRSA_SSL_CONF=/config/ssl/openssl-easyrsa.cnf \ EASYRSA_SAFE_CONF=/config/ssl/safessl-easyrsa.cnf \ - EASYRSA_TEMP_FILE=/config/temp \ - OVPN_ROOT=/config \ - OVPN_HOOKS=/config/hooks \ - OVPN_RUN=system.conf + EASYRSA_TEMP_FILE=/config/tmp/temp # Install packages -RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/main/" >> /etc/apk/repositories && \ - apk add --no-cache \ +RUN apk add --no-cache \ # Core packages - bash sudo iptables ip6tables git openvpn easy-rsa && \ + bash \ + easy-rsa \ + iptables \ + ip6tables \ + openvpn \ + python3 \ + sudo && \ # Link easy-rsa in bin directory ln -s ${EASYRSA}/easyrsa /usr/local/bin && \ # Link python3 also as python + ln -s /usr/bin/pip3 /usr/bin/pip && \ ln -s /usr/bin/python3 /usr/bin/python && \ # Remove any temporary files created by apk rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* && \ # Add permission for network management to user abc - echo "abc ALL=(ALL) NOPASSWD: /sbin/ip, /sbin/ip6tables, /sbin/ip6tables-compat, /sbin/ip6tables-compat-restore, /sbin/ip6tables-compat-save, /sbin/ip6tables-restore, /sbin/ip6tables-restore-translate, \ - /sbin/ip6tables-save, /sbin/ip6tables-translate, /sbin/iptables, /sbin/iptables-compat, /sbin/iptables-compat-restore, /sbin/iptables-compat-save, \ - /sbin/iptables-restore, /sbin/iptables-restore-translate, /sbin/iptables-save, /sbin/iptables-translate, /sbin/route" \ - >> /etc/sudoers.d/abc + echo "${CONTAINER_USER} ALL=(ALL) NOPASSWD: \ + /sbin/ip, \ + /sbin/ip6tables, \ + /sbin/ip6tables-compat, \ + /sbin/ip6tables-compat-restore, \ + /sbin/ip6tables-compat-save, \ + /sbin/ip6tables-restore, \ + /sbin/ip6tables-restore-translate, \ + /sbin/ip6tables-save, \ + /sbin/ip6tables-translate, \ + /sbin/iptables, \ + /sbin/iptables-compat, \ + /sbin/iptables-compat-restore, \ + /sbin/iptables-compat-save, \ + /sbin/iptables-restore, \ + /sbin/iptables-restore-translate, \ + /sbin/iptables-save, \ + /sbin/iptables-translate, \ + /sbin/route" \ + >> /etc/sudoers.d/${CONTAINER_USER} # Add repo files to image COPY root/ / - -# Configure -RUN chmod +x /app/bin/* && \ - chmod +x /usr/local/sbin/* && \ - chmod -R 0644 /etc/logrotate.d diff --git a/Dockerfile.armhf b/Dockerfile.armhf new file mode 100644 index 0000000..aeaaaf5 --- /dev/null +++ b/Dockerfile.armhf @@ -0,0 +1,88 @@ +# +# Base image +# @see https://github.com/SloCompTech/docker-baseimage +# +FROM slocomptech/baseimage:alpine-armhf + +# Build arguments +ARG BUILD_DATE +ARG VCS_REF +ARG VCS_SRC +ARG VERSION + +# +# Image labels +# @see https://github.com/opencontainers/image-spec/blob/master/annotations.md +# @see http://label-schema.org/rc1/ +# @see https://semver.org/ +# +LABEL org.opencontainers.image.title="OpenVPN Server" \ + org.label-schema.name="OpenVPN Server" \ + org.opencontainers.image.description="Docker image with OpenVPN server" \ + org.label-schema.description="Docker image with OpenVPN server" \ + org.opencontainers.image.url="https://github.com/SloCompTech/docker-openvpn" \ + org.label-schema.url="https://github.com/SloCompTech/docker-openvpn" \ + org.opencontainers.image.authors="Martin Dagarin " \ + org.opencontainers.image.version=$VERSION \ + org.label-schema.version=$VERSION \ + org.opencontainers.image.revision=$VCS_REF \ + org.label-schema.vcs-ref=$VCS_REF \ + org.opencontainers.image.source=$VCS_SRC \ + org.label-schema.vcs-url=$VCS_SRC \ + org.opencontainers.image.created=$BUILD_DATE \ + org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.schema-version="1.0" + + +# +# Environment variables +# @see https://github.com/OpenVPN/easy-rsa/blob/master/doc/EasyRSA-Advanced.md +# +ENV EASYRSA=/usr/share/easy-rsa \ + EASYRSA_PKI=/config/pki \ + EASYRSA_VARS_FILE=/config/ssl/vars \ + #EASYRSA_SSL_CONF=/config/ssl/openssl-easyrsa.cnf \ + EASYRSA_SAFE_CONF=/config/ssl/safessl-easyrsa.cnf \ + EASYRSA_TEMP_FILE=/config/tmp/temp + +# Install packages +RUN apk add --no-cache \ + # Core packages + bash \ + easy-rsa \ + iptables \ + ip6tables \ + openvpn \ + python3 \ + sudo && \ + # Link easy-rsa in bin directory + ln -s ${EASYRSA}/easyrsa /usr/local/bin && \ + # Link python3 also as python + ln -s /usr/bin/pip3 /usr/bin/pip && \ + ln -s /usr/bin/python3 /usr/bin/python && \ + # Remove any temporary files created by apk + rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* && \ + # Add permission for network management to user abc + echo "${CONTAINER_USER} ALL=(ALL) NOPASSWD: \ + /sbin/ip, \ + /sbin/ip6tables, \ + /sbin/ip6tables-compat, \ + /sbin/ip6tables-compat-restore, \ + /sbin/ip6tables-compat-save, \ + /sbin/ip6tables-restore, \ + /sbin/ip6tables-restore-translate, \ + /sbin/ip6tables-save, \ + /sbin/ip6tables-translate, \ + /sbin/iptables, \ + /sbin/iptables-compat, \ + /sbin/iptables-compat-restore, \ + /sbin/iptables-compat-save, \ + /sbin/iptables-restore, \ + /sbin/iptables-restore-translate, \ + /sbin/iptables-save, \ + /sbin/iptables-translate, \ + /sbin/route" \ + >> /etc/sudoers.d/${CONTAINER_USER} + +# Add repo files to image +COPY root/ / diff --git a/README.md b/README.md index e4b7cec..316b4e9 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,6 @@ services: # If you want to build from source add build: build: context: . - cache_from: - - lsiobase/alpine.python3:latest sysctls: # For IPv6 - net.ipv6.conf.all.disable_ipv6=0 - net.ipv6.conf.default.forwarding=1 @@ -68,11 +66,13 @@ services: |**Parameter**|**Function**| |:-----------:|:----------:| +|`-e FAIL_MODE=hard`|Restart whole container on error| |`-e PUID=1000`|for UserID - see below for explanation| |`-e PGID=1000`|for GroupID - see below for explanation| -|`-e OVPN_NFW=true`|Disable any firewall related rules to be created, modified ... (must be implemented in example)| -|`-e OVPN_PERINT=true`|Enable persistent TUN interface| +|`-e PERSISTENT_INTERFACE=true`|Enable persistent TUN interface| +|`-e USE_FIREWALL=false`|Disable any firewall related rules to be created, modified ... (must be implemented in example)| |`-v /config`|All the config files including OpenVPNs reside here| +|`-v /log`|Log files reside here| See also: [EasyRSA](https://github.com/OpenVPN/easy-rsa/blob/master/doc/EasyRSA-Advanced.md) @@ -104,13 +104,13 @@ If you are new to containers please see rather [Detailed first setup guide](docs 2. At this point you will have bash shell which runs in container. Now run following commands to setup your PKI: ``` bash - ovpn_init [nopass] # Inits PKI + ovpn pki init [nopass] # Inits PKI ``` 3. Setup OpenVPN config based on example `basic_nat` with configuration wizard: ``` bash - ovpn_enconf basic_nat + ovpn enconf basic_nat #Out interface [eth0]: #Protocol udp, tcp, udp6, tcp6 [udp]: #VPN network [10.0.0.0]: @@ -125,13 +125,13 @@ If you are new to containers please see rather [Detailed first setup guide](docs ``` bash # Generates client certificates - ovpn_client add [nopass] + ovpn client add [nopass] - # Generates client config file and prints it to screen (redirect to file) - ovpn_client ovpn > .ovpn + # Generates client config file and saves it to /config/tmp + ovpn client ovpn # OR BETTER SOLLUTION: Run outside container - docker exec -it ovpn_client ovpn > .ovpn + docker exec -it ovpn client ovpnp > .ovpn ``` 5. Exit container with `exit`, then it will destroy itself. @@ -144,6 +144,10 @@ For more infromation see: - **configuration example directory** (for more info about example) - [Contributing](CONTRIBUTING.md) (for explanation how container works, how to write an example config ...) +### Client mode + +Just put *.ovpn* file in `/config/openvpn/config` and restart container. + ## Troubleshooting - [OpenVPN troubleshoot guide](https://community.openvpn.net/openvpn/wiki/HOWTO#Troubleshooting) @@ -170,4 +174,4 @@ Wanted features (please help implement): ## Versions -See [CHANGELOG](CHANGELOG.md) \ No newline at end of file +See [CHANGELOG](CHANGELOG.md) diff --git a/docker-compose.yml b/docker-compose.yml index fb4a968..4709628 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,8 +20,6 @@ services: restart: on-failure build: context: . - cache_from: - - lsiobase/alpine.python3:latest sysctls: # For IPv6 - net.ipv6.conf.all.disable_ipv6=0 - net.ipv6.conf.default.forwarding=1 diff --git a/docs/Commands.md b/docs/Commands.md new file mode 100644 index 0000000..bc76f44 --- /dev/null +++ b/docs/Commands.md @@ -0,0 +1,101 @@ +# Commands + +This chapter shows available commands. + +``` bash +$ ovpn help +Usage: ovpn COMMAND [ARGS..] + +Commands: + backup # Creates backup of configuration files + client [add|ovpn|ban|revoke|remove|delete|help] [NAME] [nopass] # Client manipulation + disconf # Deletes active config + enconf EXAMPLE_CONFIG_NAME [wizard args] # Enable example config + pki [init|remove|delete] # Public Key Intrastructure + restore ARCHIVE_FILE # Restores backup +``` + +## ovpn backup + +This command backups your configration into **.tar.gz** archive and puts it into `/config/backup` directory. + +### Usage + +``` bash +$ ovpn backup +``` + +**Note:** Store your backups in a **SECURE** way, because they are **unencrypted**. + +## ovpn client + +This commands manages clients of your OpenVPN server. + +``` bash +$ ovpn client help +Usage: ovpn_client COMMAND [ARGS] + +Commands: + add [NAME [nopass]] # Creates certificates for client + ovpn NAME # Generates .ovpn file (saves to tmp) + revoke|ban NAME # Adds client to CRL + remove|delete NAME # Removes client config +``` + +**Note:** First you need to use `add` to create client certificates, before you can use `ovpn` command. + +### Create .ovpn file for client + +``` bash +$ ovpn client add CLIENTNAME [nopass] +$ ovpn client ovpn CLIENTNAME +# .ovpn file is saved to /config/tmp +``` + +## ovpn disconf + +This command deletes your active configuration. **Container restart** is needed for changes to take affect. + +``` +$ ovpn disconf +``` + +**NOTE:** This command does not delete PKI. + +## ovpn enconf + +This command enables OpenVPN config based on config example. If config name isn't specified it prints out config list. + +``` +$ ovpn enconf help +Usage: ovpn_enconf CONFIG_NAME [wizard args...] + +Configs: + +``` + +**Note:** Please read example documentation to understand how to use it. +**Warning:** Some examples automaticaly add firewall rules, so if you are using host networking make sure to check **iptables** for correct configuration. +**Tip:** If you modifed config in a way that others might need same configuration, consider making new example. + +### Enable basic config + +``` bash +$ ovpn enconf basic_nat +``` + +## ovpn pki + +This command handles PKI, which is needed for using TLS on server. + +``` bash +$ ovpn pki help +Usage: ovpn_pki COMMAND + +Commands: + delete|remove # Removes PKI + init [nopass] # Init PKI (in /config/pki) +``` + +**Note:** Best practise is to use password for your PKI. Password is only needed for signing new certificates (when adding new clients). If you don't want your PKI certificate protected with password, add `nopass` parameter. +**Note:** In this process you need to enter PKI password serveral times, because a lot of things are generated. diff --git a/docs/README.md b/docs/README.md index 0cce3e8..cd51976 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,88 +2,5 @@ ## Table of content -1. Commands - +- [Commands](Commands.md) - [Simple setup guide](SetupGuide.md) - -## Commands - -This section explains commands available for use. - -### Command List - -|**Command**|**Description**| -|:---------:|:-------------:| -|`ovpn_backup`|Backups your configration| -|`ovpn_client`|Manages clients| -|`ovpn_disconf`|Deletes active OpenVPN config| -|`ovpn_enconf`|Enables OpenVPN config from examples| -|`ovpn_init`|Inits PKI| - -#### ovpn_backup - -This command backups your configration into *.tar.gz* archive and puts it into `/config/backup` directory. - -``` -Usage: ovpn_backup COMMAND - -Commands: - all # Backup whole config directory" - pki # Backup PKI files" - hooks # Backup hooks" - openvpn # Backup openvpn live config" -``` - -**Note:** Store your backups in a **SECURE** way, because they are unecrypted. - -#### ovpn_client - -This commands manages clients of your OpenVPN server. - -``` -Usage: ovpn_client COMMAND [ARGS] - -Commands: - add [NAME [nopass]] # Creates certificates for client - ovpn NAME # Builds .ovpn file - revoke|ban|delete|remove NAME # Removes client -``` - -**Note:** First you need to use `add` to create client certificates, before you can use `ovpn` command. - -#### ovpn_disconf - -This command deletes your active configuration. **Container restart** is needed for changes to take affect. - -``` -Usage: ovpn_disconf -``` - -**NOTE:** This command does not delete PKI. - -#### ovpn_enconf - -This command enables OpenVPN config based on config example. If config name isn't specified it prints out config list. - -``` -Usage: ovpn_enconf CONFIG_NAME [wizard args...] - -Configs: - -``` - -**Note:** Please read example documentation to understand how to use it. -**Warning:** Some examples automaticaly add firewall rules, so if you are using host networking make sure to check **iptables** for correct configuration. -**Tip:** If you modifed config in a way that others might need same configuration, consider making new example. - -#### ovpn_init - -This command inits your PKI in `/config/pki` folder. You need to run this command only once. - -``` -Usage: ovpn_init [nopass] -``` - -**Note:** Best practise is to use password for your PKI. Password is only needed for signing new certificates (when adding new clients). If you don't want your PKI certificate protected with password, add `nopass` parameter. -**Note:** In this process you need to enter PKI password serveral times, because a lot of things are generated. - diff --git a/docs/SetupGuide.md b/docs/SetupGuide.md index b714a9c..837f488 100644 --- a/docs/SetupGuide.md +++ b/docs/SetupGuide.md @@ -14,7 +14,7 @@ This is simple setup guide to help you get started. It uses the simplest configu 2. At this point you will have bash shell which runs in container. Now run following commands to **setup your PKI**: ``` bash - ovpn_init [nopass] # Inits PKI + ovpn pki init [nopass] # Inits PKI #CA settings are located in /config/ssl/vars #Did you modified the file or are you planing to enter values interactively ? #[y/N]: y @@ -94,7 +94,7 @@ This is simple setup guide to help you get started. It uses the simplest configu 3. Setup OpenVPN config based on example `basic_nat` with configuration wizard: ``` bash - ovpn_enconf basic_nat + ovpn enconf basic_nat #Out interface [eth0]: #Protocol udp, tcp, udp6, tcp6 [udp]: #VPN network [10.0.0.0]: @@ -111,16 +111,16 @@ This is simple setup guide to help you get started. It uses the simplest configu ``` bash # Generates client certificates - ovpn_client add [nopass] + ovpn client add [nopass] - # Generates client config file and prints it to screen (redirect to file) - ovpn_client ovpn > .ovpn + # Generates client config file and saves it to /config/tmp + ovpn client ovpn # OR BETTER SOLLUTION: Run outside container - docker exec -it ovpn_client ovpn > .ovpn + docker exec -it ovpn client ovpnp > .ovpn ``` -**Note:** Client config files MUST be transported to your devices via **SECURE** methon such as USB (email is considered **INSECURE**). +**Note:** Client config files MUST be transported to your devices via **SECURE** method such as USB (email is considered **INSECURE**). 5. Exit container with `exit`, then it will destroy itself. 6. Now you can create config file outside container, mentioned above. diff --git a/hooks/build b/hooks/build index 26a5952..15ba3d1 100644 --- a/hooks/build +++ b/hooks/build @@ -9,8 +9,8 @@ echo "Building image" docker build \ - --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ - --build-arg VCS_REF=`git rev-parse --short HEAD` \ - --build-arg VCS_SRC="https://github.com/SloCompTech/docker-openvpn/commit/$SOURCE_COMMIT" \ - --build-arg VERSION="$SOURCE_BRANCH" \ - -t $IMAGE_NAME . \ No newline at end of file + --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ + --build-arg VCS_REF=`git rev-parse --short HEAD` \ + --build-arg VCS_SRC="https://github.com/SloCompTech/docker-openvpn/commit/$SOURCE_COMMIT" \ + --build-arg VERSION="$SOURCE_BRANCH" \ + -t $IMAGE_NAME . \ No newline at end of file diff --git a/root/app/bin/ovpn_backup b/root/app/bin/ovpn_backup deleted file mode 100755 index 6ecc905..0000000 --- a/root/app/bin/ovpn_backup +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# -# Backup sciript -# - -ARCHIVE_CMD="tar --exclude=$OVPN_ROOT/backup -zcvf" - -# User permission fix -if [ "$USER" != "abc" ]; then - RUNAS="sudo -E -u abc" -else - RUNAS="" -fi - -function usage() { - echo "Usage: ovpn_backup COMMAND" - echo "" - echo "Commands:" - echo " all # Backup whole config directory" - echo " pki # Backup PKI files" - echo " hooks # Backup hooks" - echo " openvpn # Backup openvpn live config" -} - -if [ $# -lt 1 ] || [ $1 = "help" ] || [ $1 = "-h" ] || [ $1 = "--help" ]; then - usage - exit 1 -fi - - - -if [ $1 = "all" ]; then - $RUNAS $ARCHIVE_CMD $OVPN_ROOT/backup/backup_all_$(date +%H%M%S%d%m%Y).tar.gz $OVPN_ROOT -elif [ $1 = "pki" ]; then - $RUNAS $ARCHIVE_CMD $OVPN_ROOT/backup/backup_pki_$(date +%H%M%S%d%m%Y).tar.gz $EASYRSA_PKI $OVPN_ROOT/ssl -elif [ $1 = "hooks" ]; then - $RUNAS $ARCHIVE_CMD $OVPN_ROOT/backup/backup_hooks_$(date +%H%M%S%d%m%Y).tar.gz $OVPN_HOOKS -elif [ $1 = "openvpn" ]; then - $RUNAS $ARCHIVE_CMD $OVPN_ROOT/backup/backup_conf_$(date +%H%M%S%d%m%Y).tar.gz $OVPN_ROOT/openvpn -else - usage - exit 1 -fi \ No newline at end of file diff --git a/root/app/bin/ovpn_client b/root/app/bin/ovpn_client deleted file mode 100755 index 36bae42..0000000 --- a/root/app/bin/ovpn_client +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash - -# -# OpenVPN client configuration generator -# - -source /app/lib/utils - -# User permission fix -if [ "$USER" != "abc" ]; then - RUNAS="sudo -E -u abc" -else - RUNAS="" -fi - -function usage() { - echo "Usage: ovpn_client COMMAND [ARGS]" - echo "" - echo "Commands:" - echo " add [NAME [nopass]] # Creates certificates for client" - echo " ovpn NAME # Builds .ovpn file" - echo " revoke|ban|delete|remove NAME # Removes client" -} - -function build_ovpn() { - if [ $# -gt 0 ]; then - # Client standard config - for file in $OVPN_ROOT/openvpn/client/*.conf - do - [ -e "$file" ] || continue - cat $file - done - - # Check if server config is using tls-crypt or tls-auth - local crypto="" - for srv_file in $OVPN_ROOT/openvpn/server/*.conf - do - crypto="$(ovpn_findopt $srv_file tls-crypt tls-auth)" - if [ -n "$crypto" ]; then - break - fi - done - - # CA - echo "" - cat $EASYRSA_PKI/ca.crt - echo "" - echo "" - - # Client certs - echo "" - cat $EASYRSA_PKI/issued/$1.crt - echo "" - - # Client key - echo "" - cat $EASYRSA_PKI/private/$1.key - echo "" - - if [ "$crypto" = "tls-crypt" ]; then - # tls-crypt - echo "" - cat $EASYRSA_PKI/ta.key - echo "" - elif [ "$crypto" = "tls-auth" ]; then - # tls-auth - echo "" - cat $EASYRSA_PKI/ta.key - echo "" - fi - fi -} - -# Check if command even set -if [ $# -lt 1 ]; then - # Invalid command - usage - exit 1 -fi - -if [ "$1" = "add" ]; then - if [ $# -eq 1 ]; then - # Cert guide - read -p "Common name:" CN - echo -n "Password protect " - P=$(yn) - if [ $P -eq 0 ]; then - $RUNAS easyrsa gen-req $CN nopass - else - $RUNAS easyrsa gen-req $CN - fi - $RUNAS easyrsa sign-req client $CN - else - # Just build cert - $RUNAS easyrsa gen-req ${@:2} - $RUNAS easyrsa sign-req client ${@:2} - fi - -elif [ "$1" = "ovpn" ]; then - if [ $# -eq 2 ]; then - build_ovpn $2 - else - usage - exit 1 - fi -elif [ "$1" = "ban" ] || [ "$1" = "remove" ] || [ "$1" = "delete"] || [ "$1" = "revoke" ] ; then - if [ $# -eq 2 ]; then - $RUNAS easyrsa revoke $2 - $RUNAS easyrsa gen-crl - else - usage - exit 1 - fi -else - usage - exit 1 -fi - - - diff --git a/root/app/bin/ovpn_disconf b/root/app/bin/ovpn_disconf deleted file mode 100755 index 91811b2..0000000 --- a/root/app/bin/ovpn_disconf +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# -# Disables OpenVPN config -# WARNING: This deletes active OpenVPN config & active hooks (/config/hooks) -# - -# Display notice -echo "This script will clear your configuration (whole openvpn directory)." -echo "Please make sure that you backed up you config and active hooks." - -# Make sure that user understands -read -p "Are you sure, you want to delete active config and hooks ? [y/N]:" sure - -# Check if operation aborted -if [ $sure != "y" ] && [ $sure != "Y" ]; then - exit 0 -fi - -# Check if config directory exists -config_path=$OVPN_ROOT/openvpn -if [ ! -d "$config_path" ]; then - echo "Config directory: $config_path does not exist" - exit 1 -fi - -# Delete server config -if [ -d "$config_path/server" ]; then - rm -rf $config_path/server/* -fi - -# Delete client config -if [ -d "$config_path/client" ]; then - rm -rf $config_path/client/* -fi - -# Delete hook scripts -if [ -d "$OVPN_ROOT/hooks" ]; then - rm -rf $OVPN_ROOT/hooks/*/* -fi \ No newline at end of file diff --git a/root/app/bin/ovpn_enconf b/root/app/bin/ovpn_enconf deleted file mode 100755 index 303fe11..0000000 --- a/root/app/bin/ovpn_enconf +++ /dev/null @@ -1,189 +0,0 @@ -#!/bin/bash - -# -# Enables OpenVPN config example -# - -source /app/lib/utils - -# User permission fix -if [ "$USER" != "abc" ]; then - RUNAS="sudo -E -u abc" -else - RUNAS="" -fi - -function usage() { - echo "Usage: ovpn_enconf CONFIG_NAME [wizard args...]" - echo "" - echo "Configs:" - local identifiers=() # Which identifiers we already printed out - - # Go through all identifiers - for folder in $OVPN_ROOT/example/config/* - do - [ -d "$folder" ] || continue - - local folder_name="$(echo $folder | sed -E 's/^\/.*\/(.*)$/\1/')" - - # Check if we already printed out that identifer - local found=0 - for i in "$identifiers" - do - if [ "$i" = "$folder_name" ]; then - found=1 - break - fi - done - if [ $found -eq 0 ]; then - # Print out new identifier - echo "$folder_name" - identifiers=($identifiers $folder_name) - fi - done -} - -# -# Install OpenVPN server configs -# @param source root -# @param dest root -# -function install_server() { - if [ $# -ne 2 ]; then - echo "Wrong usage: install_server" - exit 2 - fi - - # Copy server config - if [ -d $1/server ]; then - # Check if destination folder exists - if [ ! -d "$2/server" ]; then - echo "$2/server does not exist" - exit 3 - fi - - $RUNAS cp -r $1/server/* $2/server - fi -} - -# -# Install OpenVPN client configs -# @param source root -# @param dest root -# -function install_client() { - if [ $# -ne 2 ]; then - echo "Wrong usage: install_client" - exit 2 - fi - - # Copy client config - if [ -d $1/client ]; then - # Check if destination folder exists - if [ ! -d "$2/client" ]; then - echo "$2/client does not exist" - exit 3 - fi - - $RUNAS cp -r $1/client/* $2/client - fi -} - -# -# Install hooks -# @param source root -# @param dest root -# -function install_hooks() { - if [ $# -ne 2 ]; then - echo "Wrong usage: install_hooks" - exit 2 - fi - - # Copy hooks - if [ -d "$1/hooks" ]; then - # Check if destination folder exists - if [ ! -d "$2/hooks" ]; then - echo "$2/hooks does not exist" - exit 3 - fi - - # Hooks directory exist, check for hooks - for conf_hook in $1/hooks/* - do - # We are only interested in directories inside hook folder - [ -d $conf_hook ] || continue - - hook_name="$(echo $folder | sed -E 's/^\/.*\/(.*)$/\1/')" - - # Skip hooks that are not in /config/hooks - if [ ! -d "$2/hooks/$hook_name" ]; then - echo "Hook $hook_name not found in hooks directory." - continue - fi - - # Copy hooks - $RUNAS cp -r $1/hooks/$hook_name/* $2/hooks/$hook_name - done - fi -} - -if [ $# -lt 1 ]; then - usage - exit 1 -fi - -if [ $# -gt 0 ]; then - # Get wanted config name - config_name=$1 - config_path=$OVPN_ROOT/example/config/$config_name - - # Check if config exists - if [ ! -d $config_path ]; then - echo "Config does not exist" - exit 2 - fi - - # TODO: Check if there is any previous config - - # Configure copy destination - if [ -f "$config_path/wizard" ] && [ -x "$config_path/wizard" ]; then - tmp_path=/tmp/wizard - - # Delete existing tmp directory - if [ -e "$tmp_path" ]; then - rm -rf $tmp_path - fi - - # Copy config to temporary folder so it can be modified - $RUNAS cp -r $config_path $tmp_path - - # Run wizard (with temporary path) - $RUNAS $config_path/wizard "$tmp_path" ${@:2} - exit_code=$? - - # If wizard exists with code other than 0, return error - if [ $exit_code -ne 0 ]; then - echo "Error while executing wizard" - exit $exit_code - fi - - # Copy wizard finished files - install_server $tmp_path $OVPN_ROOT/openvpn - install_client $tmp_path $OVPN_ROOT/openvpn - install_hooks $tmp_path $OVPN_ROOT - - # Remove temporary directory - rm -rf $tmp_path - else - # Directly copy files - install_server $config_path $OVPN_ROOT/openvpn - install_client $config_path $OVPN_ROOT/openvpn - install_hooks $config_path $OVPN_ROOT - - # Wizard not available - echo "Sorry, wizard not available for this config" - echo "" - echo "Please edit config files in /config/openvpn to suite your needs" - fi -fi \ No newline at end of file diff --git a/root/app/bin/ovpn_findopt b/root/app/bin/ovpn_findopt deleted file mode 100644 index 3baf67a..0000000 --- a/root/app/bin/ovpn_findopt +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python - -# -# Finds first of specified options in config file -# @author Martin Dagarin -# @version 1 -# @since 19/03/2019 -# -# Usage: ovpn_findopt ... -# -import sys - -# Import libraries included in this docker -sys.path.insert(0, '/app/lib') -import libovpn - -if len(sys.argv) < 3: - # Invalid command - print("") - sys.exit(0) - -config_file = sys.argv[1] -found = libovpn.conf_optFindFirst(config_file, sys.argv[2:]) - -if found is not None: - print(found) -else: - print("") \ No newline at end of file diff --git a/root/app/bin/ovpn_init b/root/app/bin/ovpn_init deleted file mode 100755 index d8befb9..0000000 --- a/root/app/bin/ovpn_init +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -# -# OpenVPN init script -# -# @see https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto -# @see https://forums.openvpn.net/viewtopic.php?t=20837 -# @see https://securitronlinux.com/bejiitaswrath/how-to-create-keys-with-easy-rsa-without-a-password-prompt/ -# -# Usage: ovpn_init [nopass] -# -# - -# User permission fix -if [ "$USER" != "abc" ]; then - RUNAS="sudo -E -u abc" -else - RUNAS="" -fi - -# -# Init CA -# -if [ -e "$OVPN_ROOT/pki" ] && [ ! -n "$OVPN_INIT_PKI"]; then - echo "PKI directory already exists. Are you SURE to init PKI again ?" - echo "You will LOSE all files in your PKI." - echo -n "[y/N]:" - read decission - if [ $decission == "y" ] || [ $decission == "Y" ]; then - # Delete PKI - rm -rf $EASYRSA_PKI - else - # Abort - exit 0 - fi -else - echo "CA settings are located in $EASYRSA_VARS_FILE" - echo "Did you modified the file or are you planing to enter values interactively ?" - echo -n "[y/N]:" - read decission - if [ $decission != "y" ] && [ $decission != "Y" ]; then - echo "Please edit $EASYRSA_VARS_FILE" - exit 0 - fi -fi - -# Init PKI directory -$RUNAS easyrsa init-pki - -# Build dh.pem -$RUNAS easyrsa gen-dh - -# Build CA -echo "Now it will build CA files for issuing new certifiactes" -echo "Please protect ca.key with secure password (used for signing new certs)" -echo "ca.key is needed only for signing new certificates, not for OpenVPN to work" - -if [ $# -gt 0 ] && [ $1 == "nopass" ]; then - $RUNAS easyrsa build-ca nopass -else - $RUNAS easyrsa build-ca -fi - -# Build server key -$RUNAS easyrsa build-server-full server nopass -$RUNAS easyrsa sign-req server server -rm $EASYRSA_PKI/reqs/server.req - -# Generate ta.key (for tls-auth,tls-crypt) -$RUNAS openvpn --genkey --secret $EASYRSA_PKI/ta.key - -# Generate CRL -$RUNAS easyrsa gen-crl diff --git a/root/app/bin/run_hooks b/root/app/bin/run_hooks deleted file mode 100755 index c0e75b5..0000000 --- a/root/app/bin/run_hooks +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -# -# Run hook scripts -# - -OVPN_HOOKS=${OVPN_HOOKS:-/config/hooks} - -function usage() { - echo "Usage: run_hooks HOOK_NAME [ARGS]" - echo "" - echo "Hooks:" - echo " auth On OpenVPN client authentication" - echo " client-connect On OpenVPN client connected" - echo " client-disconnect On OpenVPN client disconnected" - echo " finish On container shutdown" - echo " init On container power on" - echo " learn-address Client Address & Routes validation" - echo " down Before/After TUN interface closed" - echo " route-up After routes are added" - echo " route-pre-down Before routes are removed" - echo " tls-verify On OpenVPN client certificate verificaton" - echo " up After TUN interface opened" -} - -# Check if hook name is set -if [ ! -n "$1" ]; then - usage - exit 1 -fi - -# Check if hook directory exist -if [ ! -d "$OVPN_HOOKS/$1" ]; then - echo "Hook $OVPN_HOOKS/$1 directory does not exist" - exit 2 -fi - -# Run each script and check for return code -for script in $OVPN_HOOKS/$1/*; do - [ -e "$script" ] || continue - - # Execute only executable files - if [ -f "$script" ] && [ -x "$script" ]; then - # Run script and pass additional args to hooks - echo "Executing hook: $script" - if [ $# -gt 2 ]; then - $script ${@:2} - else - $script - fi - - # Check for error while executing script - exit_status=$? - if [ $exit_status -ne 0 ]; then - # In case one of the hook files fails, everything fails - echo "$script exited with $exit_status." - exit $exit_status - fi - fi -done - -# Exit with success -exit 0 \ No newline at end of file diff --git a/root/app/hookBaseFirewallDestroy.sh b/root/app/hookBaseFirewallDestroy.sh new file mode 100755 index 0000000..eaccf94 --- /dev/null +++ b/root/app/hookBaseFirewallDestroy.sh @@ -0,0 +1,15 @@ +#!/usr/bin/with-contenv bash + +# +# Pre-checks for firewall destruction related hooks +# + +# Check if firewall rules are disabled +if [ "$USE_FIREWALL" == "false" ]; then + exit 0 # Don't use fw rules +fi + +# Don't run if persistent interface +if [ "$PERSISTENT_INTERFACE" == "true" ]; then + exit 0 +fi diff --git a/root/app/hookBaseFirewallSetup.sh b/root/app/hookBaseFirewallSetup.sh new file mode 100755 index 0000000..fa4266a --- /dev/null +++ b/root/app/hookBaseFirewallSetup.sh @@ -0,0 +1,20 @@ +#!/usr/bin/with-contenv bash + +# +# Pre-checks for firewall setup related hooks +# + +# Check if firewall rules are disabled +if [ "$USE_FIREWALL" == "false" ]; then + exit 0 # Don't use fw rules +fi + +# Run script only once if persistent interface +# @see https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself +if [ "$PERSISTENT_INTERFACE" == "true" ]; then + flagFile="$(realpath $0).flag" + if [ -f "$flagFile" ]; then + exit 0 # Flag file exists, exit + fi + touch $flagFile +fi \ No newline at end of file diff --git a/root/app/lib/settings b/root/app/lib/settings deleted file mode 100644 index 0d46f2d..0000000 --- a/root/app/lib/settings +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/with-contenv bash - -# -# Settings functions -# - -# -# Checks if TUN interface is supposed to be persistant -# @return 1 if persistant, 0 if not -# -function intPersistant() { - if [ ! -n "$OVPN_PERINT" ] || ([ "$OVPN_PERINT" != "true" ] && [ "$OVPN_PERINT" != "1" ]); then - return 0 # Not persistant by default - else - return 1 # Persistant - fi -} - -# -# Checks if we use firewall rules -# @return 1 if yes, 0 if not -# -function useFW() { - if [ ! -n "$OVPN_NFW" ] || ([ "$OVPN_NFW" != "true" ] && [ "$OVPN_NFW" != "1" ]); then - return 1 # yes by default - else - return 0 # No - fi -} - -# -# Checks if TUN interface exists already -# @return 0 if found, 1 if not found -# -function intTunExists() { - RES=`cat /proc/net/dev | grep tun0` - if [ -n "$RES" ]; then - return 0 # Found - else - return 1 # Not found - fi -} \ No newline at end of file diff --git a/root/app/lib/utils b/root/app/lib/utils deleted file mode 100644 index 9706a15..0000000 --- a/root/app/lib/utils +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/with-contenv bash - -# -# Additional functions -# - -function yn() { - local defaultOption=${1:-'n'} - local defaultText='[y/N]:' - if [ defaultOption = 'y' ]; then - defaultText='[Y/n]:' - fi - read -p "$defaultText" decision - if [ "$decision" = 'y' ] || [ "$decision" = 'Y' ]; then - echo '1' - else - echo '0' - fi -} - -# -# Checks if item is in array -# @param $1 Array as "${array[@]}" -# @param $2 String we are looking for -# @return 0 If not in array, 1 if in array -# -# arrayContains array "element" -# echo $? -# -function arrayContains() { - # Check if empty - if [ ! -n "$1" ]; then - return 0 - fi - - local array="$1[@]" - # Check array for element - for element in "${!array}"; do - - # Check if we found element in array - if [ "$2" = "$element" ]; then - return 1 - fi - done - - # Element not found - return 0 -} - -# -# Function that makes sure, that script runs only once -# @param $1 ID -# -function run_once() { - if [ -f "$1" ]; then # Check if file (as flag) exists - exit 0 - fi - touch $1 # Create flag - chown abc:abc $1 # Change permission -} \ No newline at end of file diff --git a/root/app/lib/libovpn.py b/root/app/libovpn.py similarity index 100% rename from root/app/lib/libovpn.py rename to root/app/libovpn.py diff --git a/root/defaults/example/README.md b/root/defaults/example/README.md index 93e03a4..f8a5f86 100644 --- a/root/defaults/example/README.md +++ b/root/defaults/example/README.md @@ -23,39 +23,31 @@ Config directory has following structure: ``` config - # Directory with your examples - client # Directory, OpenVPN client config files - .conf # Partial OpenVPN client config file - server # Directory, OpenVPN server config files - .conf # Partial OpenVPN server config file - hooks # Directory with hooks for this example - # Directory, name of hook - # Executable scripts - wizard # Setup script, run on `ovpn_enconf` command. - Readme.md # Info about example, what to configure + # Directory with your examples + client # Directory, OpenVPN client config files + .conf # Partial OpenVPN client config file + config # Directory, OpenVPN server config files + .conf # Partial OpenVPN server config file + hooks # Directory with hooks for this example + # Directory, name of hook + # Executable scripts + wizard # Setup script, run on `ovpn_enconf` command. + Readme.md # Info about example, what to configure ``` ### Hooks - start hook file with - ``` bash - #!/usr/bin/with-contenv bash - - source /app/lib/settings - source /app/lib/utils - ``` + ``` bash + #!/usr/bin/with-contenv bash + ``` - if hooks call any **firewall** related commands add after above code and before any commands - ``` bash - # Check if firewall rules are disabled - useFW - if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 - fi - ``` + ``` bash + source /app/hookBaseFirewall.sh + ``` - also check the examples how persistent interface is handled, so you don't create iptables mess (running init, up script once, never call down, finish) @@ -70,16 +62,16 @@ config ### Wizard Wizard is script that helps user to simply configure your example to his needs. -User will call `ovpn_enconf CONFIG_NAME [wizard args]` to load your example in server config. +User will call `ovpn enconf CONFIG_NAME [wizard args]` to load your example in server config. Then there are two options: 1. User manualy configure settings in `/config/openvpn` folder 2. Your **wizard** script, configures files which will be copied to `/config/openvpn` - - Configuration files are copied to temporary location (so they can be modified) - - `wizard` script will be called with temporary location as first argument `$1` (folder has same structure as in examples) - - Your `wizard` script **MUST** only modify files in temporary location. - - When your wizard exits with code 0, files are copied from temporary location to config folder. + - Configuration files are copied to temporary location (so they can be modified) + - `wizard` script will be called with temporary location as first argument `$1` (folder has same structure as in examples) + - Your `wizard` script **MUST** only modify files in temporary location. + - When your wizard exits with code 0, files are copied from temporary location to config folder. ## General hooks @@ -90,8 +82,8 @@ Hooks are located in `hook` directory. Please follow hook guidelines: - File name: **hook_\** - At the top of the script - - Optionaly copyright notice - - What this hook does - - Setttings with comments and an example settings values + - Optionaly copyright notice + - What this hook does + - Setttings with comments and an example settings values -**Note:** All hooks run as non-root user so instead of using `ip` and `iptables` use `ovpn-ip`, `ovpn-iptables`, `ovpn-ip6tables` (see [/root/usr/local/sbin](/usr/local/sbin)). \ No newline at end of file +**Note:** All hooks run as non-root user so instead of using `ip` and `iptables` use `ovpn-ip`, `ovpn-iptables`, `ovpn-ip6tables` (see [/root/usr/local/sbin](/usr/local/sbin)). diff --git a/root/defaults/example/config/basic_nat/README.md b/root/defaults/example/config/basic_nat/README.md index 8c86c80..a8ef966 100644 --- a/root/defaults/example/config/basic_nat/README.md +++ b/root/defaults/example/config/basic_nat/README.md @@ -17,4 +17,4 @@ ovpn_enconf basic_nat #Public IP or domain of server: #DNS1 [8.8.8.8]: #DNS2 [8.8.4.4]: -``` \ No newline at end of file +``` diff --git a/root/defaults/example/config/basic_nat/client/client.conf b/root/defaults/example/config/basic_nat/client/client.conf index 88587cc..5c956c7 100644 --- a/root/defaults/example/config/basic_nat/client/client.conf +++ b/root/defaults/example/config/basic_nat/client/client.conf @@ -10,8 +10,6 @@ client dev tun0 proto $PROTO nobind -pull - # Remote info remote $SERVER_IP $PORT @@ -34,4 +32,3 @@ group nogroup # CA remote-cert-tls server - diff --git a/root/defaults/example/config/basic_nat_wlp/server/server.conf b/root/defaults/example/config/basic_nat/config/server.conf similarity index 76% rename from root/defaults/example/config/basic_nat_wlp/server/server.conf rename to root/defaults/example/config/basic_nat/config/server.conf index 52d786e..995bf6d 100644 --- a/root/defaults/example/config/basic_nat_wlp/server/server.conf +++ b/root/defaults/example/config/basic_nat/config/server.conf @@ -17,14 +17,14 @@ push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS $DNS1" push "dhcp-option DNS $DNS2" -ifconfig-pool-persist tmp/ipp.txt +ifconfig-pool-persist /config/tmp/ipp.txt # CA files -ca pki/ca.crt -cert pki/issued/server.crt -key pki/private/server.key -dh pki/dh.pem -tls-crypt pki/ta.key +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key remote-cert-tls client # Connection settings diff --git a/root/defaults/example/config/basic_nat/hooks/down/10-network.sh b/root/defaults/example/config/basic_nat/hooks/down/10-network.sh index b965678..98a1414 100755 --- a/root/defaults/example/config/basic_nat/hooks/down/10-network.sh +++ b/root/defaults/example/config/basic_nat/hooks/down/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear @@ -35,4 +21,3 @@ ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m # Disable NAT for VPN traffic ovpn-iptables -t nat -D POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" - diff --git a/root/defaults/example/config/basic_nat/hooks/finish/10-network.sh b/root/defaults/example/config/basic_nat/hooks/finish/10-network.sh index 94e74cd..9b2920f 100755 --- a/root/defaults/example/config/basic_nat/hooks/finish/10-network.sh +++ b/root/defaults/example/config/basic_nat/hooks/finish/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear @@ -31,4 +17,4 @@ ovpn-iptables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m c ovpn-iptables -D INPUT -p icmp --icmp-type 8 -j ACCEPT # Accept all forwarded traffic -ovpn-iptables -P FORWARD ACCEPT \ No newline at end of file +ovpn-iptables -P FORWARD ACCEPT diff --git a/root/defaults/example/config/basic_nat/hooks/init/10-network.sh b/root/defaults/example/config/basic_nat/hooks/init/10-network.sh index 890870e..c9e3c38 100755 --- a/root/defaults/example/config/basic_nat/hooks/init/10-network.sh +++ b/root/defaults/example/config/basic_nat/hooks/init/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/init/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization @@ -36,4 +22,4 @@ ovpn-iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m c ovpn-iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT # Drop all forwarded traffic -ovpn-iptables -P FORWARD DROP \ No newline at end of file +ovpn-iptables -P FORWARD DROP diff --git a/root/defaults/example/config/basic_nat/hooks/up/10-network.sh b/root/defaults/example/config/basic_nat/hooks/up/10-network.sh index 228b553..f551d8c 100755 --- a/root/defaults/example/config/basic_nat/hooks/up/10-network.sh +++ b/root/defaults/example/config/basic_nat/hooks/up/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/up/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization @@ -35,4 +21,3 @@ ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m # Preform NAT for VPN traffic ovpn-iptables -t nat -A POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" - diff --git a/root/defaults/example/config/basic_nat/wizard b/root/defaults/example/config/basic_nat/wizard index f797867..e2bc98c 100755 --- a/root/defaults/example/config/basic_nat/wizard +++ b/root/defaults/example/config/basic_nat/wizard @@ -17,7 +17,7 @@ import sys, os # Import libraries included in this docker -sys.path.insert(0, '/app/lib') +sys.path.insert(0, '/app') import libovpn # Check if temporary path was passed to this script @@ -46,45 +46,45 @@ if len(protocol) == 0: # Select network network = input("VPN network [10.0.0.0]:") if len(network) == 0: - network = "10.0.0.0" + network = "10.0.0.0" # Select port port = input("Port [1194]:") if len(port) == 0: - port="1194" + port="1194" # Select Public IP or domain public = input("Public IP or domain of server:") if len(public) == 0: - print("Invalid Public IP") - sys.exit(4) + print("Invalid Public IP") + sys.exit(4) # DNS servers dns1 = input("DNS1 [8.8.8.8]:") if len(dns1) == 0: - dns1 = "8.8.8.8" + dns1 = "8.8.8.8" dns2 = input("DNS2 [8.8.4.4]:") if len(dns2) == 0: - dns2 = "8.8.4.4" + dns2 = "8.8.4.4" # Write to server config vars = [ - ("$OUT_INT", out_int), - ("$PROTO", protocol), - ("$PORT", port), - ("$NETWORK_ADDRESS", network), - ("$SERVER_IP", public), - ("$DNS1", dns1), - ("$DNS2", dns2) + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) ] # Process config files confs = [ - "/server/server.conf", - "/client/client.conf", - "/hooks/down/10-network.sh", - "/hooks/up/10-network.sh" + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" ] for config_file in confs: - libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_ipv6/README.md b/root/defaults/example/config/basic_nat_ipv6/README.md new file mode 100644 index 0000000..f269e58 --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/README.md @@ -0,0 +1,21 @@ +# basic_nat_ipv6 + +Features: + +- Works out of the box on bridge or host network +- NAT (Network translation protocol) +- Has configuration wizard +- LAN protection (does not allow traffic to LANs connected to server) + +## Configure + +``` bash +ovpn_enconf basic_nat +#Protocol udp, tcp, udp6, tcp6 [udp]: +#VPN network [10.0.0.0]: +#VPN IPv6 network with CIDR [2001:db8::/32]: +#Port [1194]: +#Public IP or domain of server: +#DNS1 [8.8.8.8]: +#DNS2 [8.8.4.4]: +``` diff --git a/root/defaults/example/config/basic_nat_ipv6/client/client.conf b/root/defaults/example/config/basic_nat_ipv6/client/client.conf new file mode 100644 index 0000000..5c956c7 --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/client/client.conf @@ -0,0 +1,34 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 2 +# @since 12/03/2019 +# + +# Basic info +client +dev tun0 +proto $PROTO +nobind + +# Remote info +remote $SERVER_IP $PORT + +# Connection settings +resolv-retry infinite +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Additional settings +compress lzo +verb 3 + +# Permissions +user nobody +group nogroup + +# CA +remote-cert-tls server diff --git a/root/defaults/example/config/basic_nat_ipv6/config/server.conf b/root/defaults/example/config/basic_nat_ipv6/config/server.conf new file mode 100644 index 0000000..4357abc --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/config/server.conf @@ -0,0 +1,46 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 3 +# @since 12/03/2019 +# + +# Basic info +proto $PROTO +port $PORT + +# Network info (local VPN network) +topology subnet +server $NETWORK_ADDRESS 255.255.255.0 +server-ipv6 $NETWORK_ADDRESS_IPV6 + +push "redirect-gateway def1 bypass-dhcp" +push "route-ipv6 ::/0" +push "dhcp-option DNS $DNS1" +push "dhcp-option DNS $DNS2" + +ifconfig-pool-persist /config/tmp/ipp.txt + +# CA files +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key +remote-cert-tls client + +# Connection settings +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Verify client certificate +verify-client-cert require + +# Additional settings +client-to-client +keepalive 10 120 +compress lzo +explicit-exit-notify 1 diff --git a/root/defaults/example/config/basic_nat_ipv6/hooks/down/10-network.sh b/root/defaults/example/config/basic_nat_ipv6/hooks/down/10-network.sh new file mode 100755 index 0000000..760b4f8 --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/hooks/down/10-network.sh @@ -0,0 +1,27 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing OpenVPN releated firewall rules" + +# Close OpenVPN port to outside +ovpn-iptables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Disable LAN protection of VPN +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 10.0.0.0/8 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 192.168.0.0/16 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 172.16.0.0/12 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" + +# Disable Routing Internet <--> VPN network +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -D FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" + +# Disable NAT for VPN traffic +ovpn-iptables -t nat -D POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" +ovpn-ip6tables -t nat -D POSTROUTING -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_ipv6/hooks/finish/10-network.sh b/root/defaults/example/config/basic_nat_ipv6/hooks/finish/10-network.sh new file mode 100755 index 0000000..09d399e --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/hooks/finish/10-network.sh @@ -0,0 +1,24 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing up basic firewall rules" + +# Accept everything from input +ovpn-iptables -P INPUT ACCEPT +ovpn-ip6tables -P INPUT ACCEPT + +# Delete: Allow established connection +ovpn-iptables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Delete: Allow ICMP ping request +ovpn-iptables -D INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -D INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Accept all forwarded traffic +ovpn-iptables -P FORWARD ACCEPT +ovpn-ip6tables -P FORWARD ACCEPT \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_ipv6/hooks/init/10-network.sh b/root/defaults/example/config/basic_nat_ipv6/hooks/init/10-network.sh new file mode 100755 index 0000000..3ab599e --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/hooks/init/10-network.sh @@ -0,0 +1,29 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up basic firewall rules" + +# +# Because default iptables rules are set to ACCEPT all connection, we need to put some +# security settings in place +# + +# Drop everything from input +ovpn-iptables -P INPUT DROP +ovpn-ip6tables -P INPUT DROP + +# Allow established connection +ovpn-iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Allow ICMP ping request +ovpn-iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -A INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Drop all forwarded traffic +ovpn-iptables -P FORWARD DROP +ovpn-ip6tables -P FORWARD DROP \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_ipv6/hooks/up/10-network.sh b/root/defaults/example/config/basic_nat_ipv6/hooks/up/10-network.sh new file mode 100755 index 0000000..4c9373b --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/hooks/up/10-network.sh @@ -0,0 +1,27 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up OpenVPN related firewall rules" + +# Open OpenVPN port to outside +ovpn-iptables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Protect LANs after VPN +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 10.0.0.0/8 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 192.168.0.0/16 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -d 172.16.0.0/12 -j REJECT -m comment --comment "Drop traffic VPN --> LANs" + +# Allow Routing Internet <--> VPN network +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -A FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" + +# Preform NAT for VPN traffic +ovpn-iptables -t nat -A POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" +ovpn-ip6tables -t nat -A POSTROUTING -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_ipv6/wizard b/root/defaults/example/config/basic_nat_ipv6/wizard new file mode 100755 index 0000000..a76cf2b --- /dev/null +++ b/root/defaults/example/config/basic_nat_ipv6/wizard @@ -0,0 +1,95 @@ +#!/usr/bin/python + +# +# Config wizard for basic_nat example +# @author Martin Dagarin +# @version 1 +# @since 19/03/2019 +# + +# Defaults: +# Protocol: udp +# Network: 10.0.0.0 +# Port: 1194 +# DNS: 8.8.8.8, 2001:4860:4860::8888 +# + +import sys, os + +# Import libraries included in this docker +sys.path.insert(0, '/app') +import libovpn + +# Check if temporary path was passed to this script +if len(sys.argv) < 2: + print("Temporary path was not passed to wizard") + sys.exit(1) +TEMP_PATH = sys.argv[1] +if not os.path.isdir(TEMP_PATH): + print("Specified directory does not exist") + sys.exit(2) + +# Select output interface +out_int = input("Out interface [eth0]:") +if len(out_int) == 0: + out_int = "eth0" + +# Select protocol +protocol = input("Protocol udp, tcp, udp6, tcp6 [udp]:") +AVAILABLE_PROTOCOLS = ["udp", "tcp", "udp6", "tcp6"] +if len(protocol) != 0 and protocol not in AVAILABLE_PROTOCOLS: + print("Invalid protocol") + sys.exit(3) +if len(protocol) == 0: + protocol = "udp" + +# Select network +network = input("VPN network [10.0.0.0]:") +if len(network) == 0: + network = "10.0.0.0" +networkv6 = input("VPN IPv6 network with CIDR [2001:db8::/32]:") +if len(network) == 0: + print("Invalid network") + sys.exit(4) + +# Select port +port = input("Port [1194]:") +if len(port) == 0: + port="1194" + +# Select Public IP or domain +public = input("Public IP or domain of server:") +if len(public) == 0: + print("Invalid Public IP") + sys.exit(5) + +# DNS servers +dns1 = input("DNS1 [8.8.8.8]:") +if len(dns1) == 0: + dns1 = "8.8.8.8" +dns2 = input("DNS2 [2001:4860:4860::8888]:") +if len(dns2) == 0: + dns2 = "2001:4860:4860::8888" + + +# Write to server config +vars = [ + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$NETWORK_ADDRESS_IPV6", networkv6), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) +] + +# Process config files +confs = [ + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" +] +for config_file in confs: + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp/README.md b/root/defaults/example/config/basic_nat_wlp/README.md index 256e8df..0e4ea53 100644 --- a/root/defaults/example/config/basic_nat_wlp/README.md +++ b/root/defaults/example/config/basic_nat_wlp/README.md @@ -17,4 +17,4 @@ ovpn_enconf basic_nat_wlp #Public IP or domain of server: #DNS1 [8.8.8.8]: #DNS2 [8.8.4.4]: -``` \ No newline at end of file +``` diff --git a/root/defaults/example/config/basic_nat_wlp/client/client.conf b/root/defaults/example/config/basic_nat_wlp/client/client.conf index 88587cc..5c956c7 100644 --- a/root/defaults/example/config/basic_nat_wlp/client/client.conf +++ b/root/defaults/example/config/basic_nat_wlp/client/client.conf @@ -10,8 +10,6 @@ client dev tun0 proto $PROTO nobind -pull - # Remote info remote $SERVER_IP $PORT @@ -34,4 +32,3 @@ group nogroup # CA remote-cert-tls server - diff --git a/root/defaults/example/config/basic_routed/server/server.conf b/root/defaults/example/config/basic_nat_wlp/config/server.conf similarity index 76% rename from root/defaults/example/config/basic_routed/server/server.conf rename to root/defaults/example/config/basic_nat_wlp/config/server.conf index 52d786e..995bf6d 100644 --- a/root/defaults/example/config/basic_routed/server/server.conf +++ b/root/defaults/example/config/basic_nat_wlp/config/server.conf @@ -17,14 +17,14 @@ push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS $DNS1" push "dhcp-option DNS $DNS2" -ifconfig-pool-persist tmp/ipp.txt +ifconfig-pool-persist /config/tmp/ipp.txt # CA files -ca pki/ca.crt -cert pki/issued/server.crt -key pki/private/server.key -dh pki/dh.pem -tls-crypt pki/ta.key +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key remote-cert-tls client # Connection settings diff --git a/root/defaults/example/config/basic_nat_wlp/hooks/down/10-network.sh b/root/defaults/example/config/basic_nat_wlp/hooks/down/10-network.sh index 746ba15..c52da9a 100755 --- a/root/defaults/example/config/basic_nat_wlp/hooks/down/10-network.sh +++ b/root/defaults/example/config/basic_nat_wlp/hooks/down/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear @@ -30,4 +16,3 @@ ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m # Disable NAT for VPN traffic ovpn-iptables -t nat -D POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" - diff --git a/root/defaults/example/config/basic_nat_wlp/hooks/finish/10-network.sh b/root/defaults/example/config/basic_nat_wlp/hooks/finish/10-network.sh index 94e74cd..db58c82 100755 --- a/root/defaults/example/config/basic_nat_wlp/hooks/finish/10-network.sh +++ b/root/defaults/example/config/basic_nat_wlp/hooks/finish/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear diff --git a/root/defaults/example/config/basic_nat_wlp/hooks/init/10-network.sh b/root/defaults/example/config/basic_nat_wlp/hooks/init/10-network.sh index 890870e..7ae8a95 100755 --- a/root/defaults/example/config/basic_nat_wlp/hooks/init/10-network.sh +++ b/root/defaults/example/config/basic_nat_wlp/hooks/init/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/init/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization diff --git a/root/defaults/example/config/basic_nat_wlp/hooks/up/10-network.sh b/root/defaults/example/config/basic_nat_wlp/hooks/up/10-network.sh index 49a166b..0f3b363 100755 --- a/root/defaults/example/config/basic_nat_wlp/hooks/up/10-network.sh +++ b/root/defaults/example/config/basic_nat_wlp/hooks/up/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/up/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization @@ -30,4 +16,3 @@ ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m # Preform NAT for VPN traffic ovpn-iptables -t nat -A POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" - diff --git a/root/defaults/example/config/basic_nat_wlp/wizard b/root/defaults/example/config/basic_nat_wlp/wizard index a1840a2..6bd45a6 100755 --- a/root/defaults/example/config/basic_nat_wlp/wizard +++ b/root/defaults/example/config/basic_nat_wlp/wizard @@ -17,74 +17,74 @@ import sys, os # Import libraries included in this docker -sys.path.insert(0, '/app/lib') +sys.path.insert(0, '/app') import libovpn # Check if temporary path was passed to this script if len(sys.argv) < 2: - print("Temporary path was not passed to wizard") - sys.exit(1) + print("Temporary path was not passed to wizard") + sys.exit(1) TEMP_PATH = sys.argv[1] if not os.path.isdir(TEMP_PATH): - print("Specified directory does not exist") - sys.exit(2) + print("Specified directory does not exist") + sys.exit(2) # Select output interface out_int = input("Out interface [eth0]:") if len(out_int) == 0: - out_int = "eth0" + out_int = "eth0" # Select protocol protocol = input("Protocol udp, tcp, udp6, tcp6 [udp]:") AVAILABLE_PROTOCOLS = ["udp", "tcp", "udp6", "tcp6"] if len(protocol) != 0 and protocol not in AVAILABLE_PROTOCOLS: - print("Invalid protocol") - sys.exit(3) + print("Invalid protocol") + sys.exit(3) if len(protocol) == 0: - protocol = "udp" + protocol = "udp" # Select network network = input("VPN network [10.0.0.0]:") if len(network) == 0: - network = "10.0.0.0" + network = "10.0.0.0" # Select port port = input("Port [1194]:") if len(port) == 0: - port="1194" + port="1194" # Select Public IP or domain public = input("Public IP or domain of server:") if len(public) == 0: - print("Invalid Public IP") - sys.exit(4) + print("Invalid Public IP") + sys.exit(4) # DNS servers dns1 = input("DNS1 [8.8.8.8]:") if len(dns1) == 0: - dns1 = "8.8.8.8" + dns1 = "8.8.8.8" dns2 = input("DNS2 [8.8.4.4]:") if len(dns2) == 0: - dns2 = "8.8.4.4" + dns2 = "8.8.4.4" # Write to server config vars = [ - ("$OUT_INT", out_int), - ("$PROTO", protocol), - ("$PORT", port), - ("$NETWORK_ADDRESS", network), - ("$SERVER_IP", public), - ("$DNS1", dns1), - ("$DNS2", dns2) + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) ] # Process config files confs = [ - "/server/server.conf", - "/client/client.conf", - "/hooks/down/10-network.sh", - "/hooks/up/10-network.sh" + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" ] for config_file in confs: - libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/README.md b/root/defaults/example/config/basic_nat_wlp_ipv6/README.md new file mode 100644 index 0000000..f402e3f --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/README.md @@ -0,0 +1,21 @@ +# basic_nat_wlp_ipv6 + +Features: + +- Works out of the box on bridge or host network +- NAT (Network translation protocol) +- Has configuration wizard +- **WITHOUT** LAN protection (does not allow traffic to LANs connected to server), so you can still access devices in LAN (but **routed** example is recommended, because here traffic is still NAT-ed) + +## Configure + +``` bash +ovpn_enconf basic_nat +#Protocol udp, tcp, udp6, tcp6 [udp]: +#VPN network [10.0.0.0]: +#VPN IPv6 network with CIDR [2001:db8::/32]: +#Port [1194]: +#Public IP or domain of server: +#DNS1 [8.8.8.8]: +#DNS2 [8.8.4.4]: +``` diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/client/client.conf b/root/defaults/example/config/basic_nat_wlp_ipv6/client/client.conf new file mode 100644 index 0000000..5c956c7 --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/client/client.conf @@ -0,0 +1,34 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 2 +# @since 12/03/2019 +# + +# Basic info +client +dev tun0 +proto $PROTO +nobind + +# Remote info +remote $SERVER_IP $PORT + +# Connection settings +resolv-retry infinite +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Additional settings +compress lzo +verb 3 + +# Permissions +user nobody +group nogroup + +# CA +remote-cert-tls server diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/config/server.conf b/root/defaults/example/config/basic_nat_wlp_ipv6/config/server.conf new file mode 100644 index 0000000..4357abc --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/config/server.conf @@ -0,0 +1,46 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 3 +# @since 12/03/2019 +# + +# Basic info +proto $PROTO +port $PORT + +# Network info (local VPN network) +topology subnet +server $NETWORK_ADDRESS 255.255.255.0 +server-ipv6 $NETWORK_ADDRESS_IPV6 + +push "redirect-gateway def1 bypass-dhcp" +push "route-ipv6 ::/0" +push "dhcp-option DNS $DNS1" +push "dhcp-option DNS $DNS2" + +ifconfig-pool-persist /config/tmp/ipp.txt + +# CA files +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key +remote-cert-tls client + +# Connection settings +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Verify client certificate +verify-client-cert require + +# Additional settings +client-to-client +keepalive 10 120 +compress lzo +explicit-exit-notify 1 diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/down/10-network.sh b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/down/10-network.sh new file mode 100755 index 0000000..0ad1e45 --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/down/10-network.sh @@ -0,0 +1,22 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing OpenVPN releated firewall rules" + +# Close OpenVPN port to outside +ovpn-iptables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Disable Routing Internet <--> VPN network +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -D FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" + +# Disable NAT for VPN traffic +ovpn-iptables -t nat -D POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" +ovpn-ip6tables -t nat -D POSTROUTING -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/finish/10-network.sh b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/finish/10-network.sh new file mode 100755 index 0000000..09d399e --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/finish/10-network.sh @@ -0,0 +1,24 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing up basic firewall rules" + +# Accept everything from input +ovpn-iptables -P INPUT ACCEPT +ovpn-ip6tables -P INPUT ACCEPT + +# Delete: Allow established connection +ovpn-iptables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Delete: Allow ICMP ping request +ovpn-iptables -D INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -D INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Accept all forwarded traffic +ovpn-iptables -P FORWARD ACCEPT +ovpn-ip6tables -P FORWARD ACCEPT \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/init/10-network.sh b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/init/10-network.sh new file mode 100755 index 0000000..3ab599e --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/init/10-network.sh @@ -0,0 +1,29 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up basic firewall rules" + +# +# Because default iptables rules are set to ACCEPT all connection, we need to put some +# security settings in place +# + +# Drop everything from input +ovpn-iptables -P INPUT DROP +ovpn-ip6tables -P INPUT DROP + +# Allow established connection +ovpn-iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Allow ICMP ping request +ovpn-iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -A INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Drop all forwarded traffic +ovpn-iptables -P FORWARD DROP +ovpn-ip6tables -P FORWARD DROP \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/up/10-network.sh b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/up/10-network.sh new file mode 100755 index 0000000..2fec22a --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/hooks/up/10-network.sh @@ -0,0 +1,22 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up OpenVPN related firewall rules" + +# Open OpenVPN port to outside +ovpn-iptables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Allow Routing Internet <--> VPN network +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -A FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" + +# Preform NAT for VPN traffic +ovpn-iptables -t nat -A POSTROUTING -s $NETWORK_ADDRESS/24 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" +ovpn-ip6tables -t nat -A POSTROUTING -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j MASQUERADE -m comment --comment "NAT traffic VPN --> Internet" \ No newline at end of file diff --git a/root/defaults/example/config/basic_nat_wlp_ipv6/wizard b/root/defaults/example/config/basic_nat_wlp_ipv6/wizard new file mode 100755 index 0000000..a76cf2b --- /dev/null +++ b/root/defaults/example/config/basic_nat_wlp_ipv6/wizard @@ -0,0 +1,95 @@ +#!/usr/bin/python + +# +# Config wizard for basic_nat example +# @author Martin Dagarin +# @version 1 +# @since 19/03/2019 +# + +# Defaults: +# Protocol: udp +# Network: 10.0.0.0 +# Port: 1194 +# DNS: 8.8.8.8, 2001:4860:4860::8888 +# + +import sys, os + +# Import libraries included in this docker +sys.path.insert(0, '/app') +import libovpn + +# Check if temporary path was passed to this script +if len(sys.argv) < 2: + print("Temporary path was not passed to wizard") + sys.exit(1) +TEMP_PATH = sys.argv[1] +if not os.path.isdir(TEMP_PATH): + print("Specified directory does not exist") + sys.exit(2) + +# Select output interface +out_int = input("Out interface [eth0]:") +if len(out_int) == 0: + out_int = "eth0" + +# Select protocol +protocol = input("Protocol udp, tcp, udp6, tcp6 [udp]:") +AVAILABLE_PROTOCOLS = ["udp", "tcp", "udp6", "tcp6"] +if len(protocol) != 0 and protocol not in AVAILABLE_PROTOCOLS: + print("Invalid protocol") + sys.exit(3) +if len(protocol) == 0: + protocol = "udp" + +# Select network +network = input("VPN network [10.0.0.0]:") +if len(network) == 0: + network = "10.0.0.0" +networkv6 = input("VPN IPv6 network with CIDR [2001:db8::/32]:") +if len(network) == 0: + print("Invalid network") + sys.exit(4) + +# Select port +port = input("Port [1194]:") +if len(port) == 0: + port="1194" + +# Select Public IP or domain +public = input("Public IP or domain of server:") +if len(public) == 0: + print("Invalid Public IP") + sys.exit(5) + +# DNS servers +dns1 = input("DNS1 [8.8.8.8]:") +if len(dns1) == 0: + dns1 = "8.8.8.8" +dns2 = input("DNS2 [2001:4860:4860::8888]:") +if len(dns2) == 0: + dns2 = "2001:4860:4860::8888" + + +# Write to server config +vars = [ + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$NETWORK_ADDRESS_IPV6", networkv6), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) +] + +# Process config files +confs = [ + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" +] +for config_file in confs: + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/basic_routed/README.md b/root/defaults/example/config/basic_routed/README.md index 1df5b0b..064a5ff 100644 --- a/root/defaults/example/config/basic_routed/README.md +++ b/root/defaults/example/config/basic_routed/README.md @@ -3,7 +3,7 @@ Features: - Has configuration wizard -- Prepared for using routing (so you will have access to LANs directly without usign NAT) +- Prepared for using routing (so you will have access to LANs directly without using NAT) ## Configure diff --git a/root/defaults/example/config/basic_routed/client/client.conf b/root/defaults/example/config/basic_routed/client/client.conf index 88587cc..5c956c7 100644 --- a/root/defaults/example/config/basic_routed/client/client.conf +++ b/root/defaults/example/config/basic_routed/client/client.conf @@ -10,8 +10,6 @@ client dev tun0 proto $PROTO nobind -pull - # Remote info remote $SERVER_IP $PORT @@ -34,4 +32,3 @@ group nogroup # CA remote-cert-tls server - diff --git a/root/defaults/example/config/basic_nat/server/server.conf b/root/defaults/example/config/basic_routed/config/server.conf similarity index 76% rename from root/defaults/example/config/basic_nat/server/server.conf rename to root/defaults/example/config/basic_routed/config/server.conf index 52d786e..995bf6d 100644 --- a/root/defaults/example/config/basic_nat/server/server.conf +++ b/root/defaults/example/config/basic_routed/config/server.conf @@ -17,14 +17,14 @@ push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS $DNS1" push "dhcp-option DNS $DNS2" -ifconfig-pool-persist tmp/ipp.txt +ifconfig-pool-persist /config/tmp/ipp.txt # CA files -ca pki/ca.crt -cert pki/issued/server.crt -key pki/private/server.key -dh pki/dh.pem -tls-crypt pki/ta.key +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key remote-cert-tls client # Connection settings diff --git a/root/defaults/example/config/basic_routed/hooks/down/10-network.sh b/root/defaults/example/config/basic_routed/hooks/down/10-network.sh index 2ade89a..f389549 100755 --- a/root/defaults/example/config/basic_routed/hooks/down/10-network.sh +++ b/root/defaults/example/config/basic_routed/hooks/down/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear @@ -27,4 +13,3 @@ ovpn-iptables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --commen # Disable Routing Internet <--> VPN network ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" - diff --git a/root/defaults/example/config/basic_routed/hooks/finish/10-network.sh b/root/defaults/example/config/basic_routed/hooks/finish/10-network.sh index 94e74cd..9b2920f 100755 --- a/root/defaults/example/config/basic_routed/hooks/finish/10-network.sh +++ b/root/defaults/example/config/basic_routed/hooks/finish/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Don't run if interface persistent -intPersistant -if [ $? -eq 1 ]; then - exit 0 -fi +source /app/hookBaseFirewallDestroy.sh # # Network clear @@ -31,4 +17,4 @@ ovpn-iptables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m c ovpn-iptables -D INPUT -p icmp --icmp-type 8 -j ACCEPT # Accept all forwarded traffic -ovpn-iptables -P FORWARD ACCEPT \ No newline at end of file +ovpn-iptables -P FORWARD ACCEPT diff --git a/root/defaults/example/config/basic_routed/hooks/init/10-network.sh b/root/defaults/example/config/basic_routed/hooks/init/10-network.sh index 890870e..c9e3c38 100755 --- a/root/defaults/example/config/basic_routed/hooks/init/10-network.sh +++ b/root/defaults/example/config/basic_routed/hooks/init/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/init/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization @@ -36,4 +22,4 @@ ovpn-iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m c ovpn-iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT # Drop all forwarded traffic -ovpn-iptables -P FORWARD DROP \ No newline at end of file +ovpn-iptables -P FORWARD DROP diff --git a/root/defaults/example/config/basic_routed/hooks/up/10-network.sh b/root/defaults/example/config/basic_routed/hooks/up/10-network.sh index 0680dd2..485cef4 100755 --- a/root/defaults/example/config/basic_routed/hooks/up/10-network.sh +++ b/root/defaults/example/config/basic_routed/hooks/up/10-network.sh @@ -1,20 +1,6 @@ #!/usr/bin/with-contenv bash -source /app/lib/settings -source /app/lib/utils - -# Check if firewall rules are disabled -useFW -if [ $? -eq 0 ]; then - # Don't use fw rules - exit 0 -fi - -# Run only once if interface persistent -intPersistant -if [ $? -eq 1 ]; then - run_once "/config/hooks/up/10-network" -fi +source /app/hookBaseFirewallSetup.sh # # Network initialization @@ -27,4 +13,3 @@ ovpn-iptables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --commen # Allow Routing Internet <--> VPN network ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" - diff --git a/root/defaults/example/config/basic_routed/wizard b/root/defaults/example/config/basic_routed/wizard index 1f6e88c..0b9afd7 100755 --- a/root/defaults/example/config/basic_routed/wizard +++ b/root/defaults/example/config/basic_routed/wizard @@ -17,74 +17,74 @@ import sys, os # Import libraries included in this docker -sys.path.insert(0, '/app/lib') +sys.path.insert(0, '/app') import libovpn # Check if temporary path was passed to this script if len(sys.argv) < 2: - print("Temporary path was not passed to wizard") - sys.exit(1) + print("Temporary path was not passed to wizard") + sys.exit(1) TEMP_PATH = sys.argv[1] if not os.path.isdir(TEMP_PATH): - print("Specified directory does not exist") - sys.exit(2) + print("Specified directory does not exist") + sys.exit(2) # Select output interface out_int = input("Out interface [eth0]:") if len(out_int) == 0: - out_int = "eth0" + out_int = "eth0" # Select protocol protocol = input("Protocol udp, tcp, udp6, tcp6 [udp]:") AVAILABLE_PROTOCOLS = ["udp", "tcp", "udp6", "tcp6"] if len(protocol) != 0 and protocol not in AVAILABLE_PROTOCOLS: - print("Invalid protocol") - sys.exit(3) + print("Invalid protocol") + sys.exit(3) if len(protocol) == 0: - protocol = "udp" + protocol = "udp" # Select network network = input("VPN network [10.0.0.0]:") if len(network) == 0: - network = "10.0.0.0" + network = "10.0.0.0" # Select port port = input("Port [1194]:") if len(port) == 0: - port="1194" + port="1194" # Select Public IP or domain public = input("Public IP or domain of server:") if len(public) == 0: - print("Invalid Public IP") - sys.exit(4) + print("Invalid Public IP") + sys.exit(4) # DNS servers dns1 = input("DNS1 [8.8.8.8]:") if len(dns1) == 0: - dns1 = "8.8.8.8" + dns1 = "8.8.8.8" dns2 = input("DNS2 [8.8.4.4]:") if len(dns2) == 0: - dns2 = "8.8.4.4" + dns2 = "8.8.4.4" # Write to server config vars = [ - ("$OUT_INT", out_int), - ("$PROTO", protocol), - ("$PORT", port), - ("$NETWORK_ADDRESS", network), - ("$SERVER_IP", public), - ("$DNS1", dns1), - ("$DNS2", dns2) + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) ] # Process config files confs = [ - "/server/server.conf", - "/client/client.conf", - "/hooks/down/10-network.sh", - "/hooks/up/10-network.sh" + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" ] for config_file in confs: - libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/basic_routed_ipv6/README.md b/root/defaults/example/config/basic_routed_ipv6/README.md new file mode 100644 index 0000000..9a67b2e --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/README.md @@ -0,0 +1,48 @@ +# basic_routed_ipv6 + +Features: + +- Has configuration wizard +- Prepared for using routing (so you will have access to LANs directly without using NAT) + +## Configure + +``` bash +ovpn_enconf basic_routed +#Protocol udp, tcp, udp6, tcp6 [udp]: +#VPN network [10.0.0.0]: +#VPN IPv6 network with CIDR [2001:db8::/32]: +#Port [1194]: +#Public IP or domain of server: +#DNS1 [8.8.8.8]: +#DNS2 [8.8.4.4]: +``` + +### Network configuration + +1. If you are using **bridge** networking mode else skip this step: + + - Assign static IP to this container + - see [docker compose networks](https://docs.docker.com/compose/compose-file/compose-file-v2/#networks), you can also check current IP of container + with `docker exec -it CONTAINERNAME ifconfig` + - Add static route on host to the container with network + + ``` bash + route add -net NETWORK netmask MASK gw CONTAINER_IP + ``` + +2. Add route to the network on your router + + - Destination IP Address: NETWORK + - Subnet mask: MASK + - Gateway: SERVERIP_OR_CONTAINERIP (IP where your OpenVPN server is running: server ip when bridge mode, container ip on host mode) + + ![Sample interface](img/img1.png) + +3. If you have Mikrotik or Cisco router make sure you have NAT correctly configured +4. Make sure you have firewall rules correctly configured on your router +5. Add additional routes in *server config* if nessesary (see [--route option](https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage)), default route is set as default gateway + + ``` OpenVPN + route network/IP [netmask] [gateway] [metric] + ``` diff --git a/root/defaults/example/config/basic_routed_ipv6/client/client.conf b/root/defaults/example/config/basic_routed_ipv6/client/client.conf new file mode 100644 index 0000000..5c956c7 --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/client/client.conf @@ -0,0 +1,34 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 2 +# @since 12/03/2019 +# + +# Basic info +client +dev tun0 +proto $PROTO +nobind + +# Remote info +remote $SERVER_IP $PORT + +# Connection settings +resolv-retry infinite +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Additional settings +compress lzo +verb 3 + +# Permissions +user nobody +group nogroup + +# CA +remote-cert-tls server diff --git a/root/defaults/example/config/basic_routed_ipv6/config/server.conf b/root/defaults/example/config/basic_routed_ipv6/config/server.conf new file mode 100644 index 0000000..4357abc --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/config/server.conf @@ -0,0 +1,46 @@ +# +# Basic OpenVPN server configuration +# @author Martin Dagarin +# @version 3 +# @since 12/03/2019 +# + +# Basic info +proto $PROTO +port $PORT + +# Network info (local VPN network) +topology subnet +server $NETWORK_ADDRESS 255.255.255.0 +server-ipv6 $NETWORK_ADDRESS_IPV6 + +push "redirect-gateway def1 bypass-dhcp" +push "route-ipv6 ::/0" +push "dhcp-option DNS $DNS1" +push "dhcp-option DNS $DNS2" + +ifconfig-pool-persist /config/tmp/ipp.txt + +# CA files +ca /config/pki/ca.crt +cert /config/pki/issued/server.crt +key /config/pki/private/server.key +dh /config/pki/dh.pem +tls-crypt /config/pki/ta.key +remote-cert-tls client + +# Connection settings +persist-key +persist-tun + +# Encryption settings +cipher AES-256-GCM + +# Verify client certificate +verify-client-cert require + +# Additional settings +client-to-client +keepalive 10 120 +compress lzo +explicit-exit-notify 1 diff --git a/root/defaults/example/config/basic_routed_ipv6/hooks/down/10-network.sh b/root/defaults/example/config/basic_routed_ipv6/hooks/down/10-network.sh new file mode 100755 index 0000000..30c83dd --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/hooks/down/10-network.sh @@ -0,0 +1,18 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing OpenVPN releated firewall rules" + +# Close OpenVPN port to outside +ovpn-iptables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -D INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Disable Routing Internet <--> VPN network +ovpn-iptables -D FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -D FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -D FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" diff --git a/root/defaults/example/config/basic_routed_ipv6/hooks/finish/10-network.sh b/root/defaults/example/config/basic_routed_ipv6/hooks/finish/10-network.sh new file mode 100755 index 0000000..09d399e --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/hooks/finish/10-network.sh @@ -0,0 +1,24 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallDestroy.sh + +# +# Network clear +# +echo "Clearing up basic firewall rules" + +# Accept everything from input +ovpn-iptables -P INPUT ACCEPT +ovpn-ip6tables -P INPUT ACCEPT + +# Delete: Allow established connection +ovpn-iptables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -D INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Delete: Allow ICMP ping request +ovpn-iptables -D INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -D INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Accept all forwarded traffic +ovpn-iptables -P FORWARD ACCEPT +ovpn-ip6tables -P FORWARD ACCEPT \ No newline at end of file diff --git a/root/defaults/example/config/basic_routed_ipv6/hooks/init/10-network.sh b/root/defaults/example/config/basic_routed_ipv6/hooks/init/10-network.sh new file mode 100755 index 0000000..3ab599e --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/hooks/init/10-network.sh @@ -0,0 +1,29 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up basic firewall rules" + +# +# Because default iptables rules are set to ACCEPT all connection, we need to put some +# security settings in place +# + +# Drop everything from input +ovpn-iptables -P INPUT DROP +ovpn-ip6tables -P INPUT DROP + +# Allow established connection +ovpn-iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" +ovpn-ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "Accept traffic from established connections" + +# Allow ICMP ping request +ovpn-iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT +ovpn-ip6tables -A INPUT -p icmp --icmp-type 128 -j ACCEPT + +# Drop all forwarded traffic +ovpn-iptables -P FORWARD DROP +ovpn-ip6tables -P FORWARD DROP \ No newline at end of file diff --git a/root/defaults/example/config/basic_routed_ipv6/hooks/up/10-network.sh b/root/defaults/example/config/basic_routed_ipv6/hooks/up/10-network.sh new file mode 100755 index 0000000..664795d --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/hooks/up/10-network.sh @@ -0,0 +1,18 @@ +#!/usr/bin/with-contenv bash + +source /app/hookBaseFirewallSetup.sh + +# +# Network initialization +# +echo "Setting up OpenVPN related firewall rules" + +# Open OpenVPN port to outside +ovpn-iptables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" +ovpn-ip6tables -A INPUT -p udp -m udp --dport $PORT -j ACCEPT -m comment --comment "Open OpenVPN port" + +# Allow Routing Internet <--> VPN network +ovpn-iptables -A FORWARD -i tun0 -s $NETWORK_ADDRESS/24 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-iptables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS/24 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" +ovpn-ip6tables -A FORWARD -i tun0 -s $NETWORK_ADDRESS_IPV6 -o $OUT_INT -j ACCEPT -m comment --comment "Allow traffic VPN --> Internet" +ovpn-ip6tables -A FORWARD -i $OUT_INT -d $NETWORK_ADDRESS_IPV6 -o tun0 -j ACCEPT -m comment --comment "Allow traffic Internet --> VPN" diff --git a/root/defaults/example/config/basic_routed_ipv6/wizard b/root/defaults/example/config/basic_routed_ipv6/wizard new file mode 100755 index 0000000..a76cf2b --- /dev/null +++ b/root/defaults/example/config/basic_routed_ipv6/wizard @@ -0,0 +1,95 @@ +#!/usr/bin/python + +# +# Config wizard for basic_nat example +# @author Martin Dagarin +# @version 1 +# @since 19/03/2019 +# + +# Defaults: +# Protocol: udp +# Network: 10.0.0.0 +# Port: 1194 +# DNS: 8.8.8.8, 2001:4860:4860::8888 +# + +import sys, os + +# Import libraries included in this docker +sys.path.insert(0, '/app') +import libovpn + +# Check if temporary path was passed to this script +if len(sys.argv) < 2: + print("Temporary path was not passed to wizard") + sys.exit(1) +TEMP_PATH = sys.argv[1] +if not os.path.isdir(TEMP_PATH): + print("Specified directory does not exist") + sys.exit(2) + +# Select output interface +out_int = input("Out interface [eth0]:") +if len(out_int) == 0: + out_int = "eth0" + +# Select protocol +protocol = input("Protocol udp, tcp, udp6, tcp6 [udp]:") +AVAILABLE_PROTOCOLS = ["udp", "tcp", "udp6", "tcp6"] +if len(protocol) != 0 and protocol not in AVAILABLE_PROTOCOLS: + print("Invalid protocol") + sys.exit(3) +if len(protocol) == 0: + protocol = "udp" + +# Select network +network = input("VPN network [10.0.0.0]:") +if len(network) == 0: + network = "10.0.0.0" +networkv6 = input("VPN IPv6 network with CIDR [2001:db8::/32]:") +if len(network) == 0: + print("Invalid network") + sys.exit(4) + +# Select port +port = input("Port [1194]:") +if len(port) == 0: + port="1194" + +# Select Public IP or domain +public = input("Public IP or domain of server:") +if len(public) == 0: + print("Invalid Public IP") + sys.exit(5) + +# DNS servers +dns1 = input("DNS1 [8.8.8.8]:") +if len(dns1) == 0: + dns1 = "8.8.8.8" +dns2 = input("DNS2 [2001:4860:4860::8888]:") +if len(dns2) == 0: + dns2 = "2001:4860:4860::8888" + + +# Write to server config +vars = [ + ("$OUT_INT", out_int), + ("$PROTO", protocol), + ("$PORT", port), + ("$NETWORK_ADDRESS", network), + ("$NETWORK_ADDRESS_IPV6", networkv6), + ("$SERVER_IP", public), + ("$DNS1", dns1), + ("$DNS2", dns2) +] + +# Process config files +confs = [ + "/config/server.conf", + "/client/client.conf", + "/hooks/down/10-network.sh", + "/hooks/up/10-network.sh" +] +for config_file in confs: + libovpn.conf_envsubst(TEMP_PATH + config_file, vars) \ No newline at end of file diff --git a/root/defaults/example/config/client_staticopts/ccd/clientCommonName b/root/defaults/example/config/client_staticopts/ccd/clientCommonName new file mode 100644 index 0000000..eb62023 --- /dev/null +++ b/root/defaults/example/config/client_staticopts/ccd/clientCommonName @@ -0,0 +1,28 @@ +# +# Set static options for client +# @see https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage +# + +# Disable client (prevent from connecting, for security compromise REVOKE client) +# disable + +# Client Static IP +# ifconfig-push IP_ADDRESS MASK + +# Generate routes through this client when connects +# iroute NETWORK [NETMASK] + +# Don't inherit global push settings +# push-reset + +# Push option to client +# push OPTION + +# Remove option from client +# push-remove OPTION + +# Client Static IPv6 +# ifconfig-ipv6-push ADDRESS/CIDR REMOTE + +# Route through client +# iroute-ipv6 ADDRESS/CIDR \ No newline at end of file diff --git a/root/defaults/system.conf b/root/defaults/openvpn/system.conf similarity index 54% rename from root/defaults/system.conf rename to root/defaults/openvpn/system.conf index f89d548..701a65b 100644 --- a/root/defaults/system.conf +++ b/root/defaults/openvpn/system.conf @@ -17,15 +17,15 @@ dev tun0 script-security 2 # Hooks call -route-up "/app/bin/run_hooks route-up" -route-pre-down "/app/bin/run_hooks route-pre-down" -up "/app/bin/run_hooks up" +route-up "/usr/local/bin/run_hooks route-up" +route-pre-down "/usr/local/bin/run_hooks route-pre-down" +up "/usr/local/bin/run_hooks up" down-pre -down "/app/bin/run_hooks down" -client-connect "/app/bin/run_hooks client-connect" -client-disconnect "/app/bin/run_hooks client-disconnect" -learn-address "/app/bin/run_hooks learn-address" -tls-verify "/app/bin/run_hooks tls-verify" +down "/usr/local/bin/run_hooks down" +client-connect "/usr/local/bin/run_hooks client-connect" +client-disconnect "/usr/local/bin/run_hooks client-disconnect" +learn-address "/usr/local/bin/run_hooks learn-address" +tls-verify "/usr/local/bin/run_hooks tls-verify" # # For username & password authentication uncomment bellow @@ -36,22 +36,22 @@ tls-verify "/app/bin/run_hooks tls-verify" #--auth-user-pass-optional # Temporary dir -tmp-dir tmp +tmp-dir /config/tmp # Logging -verb 3 +verb 1 mute 100 -#log-append log/openvpn.log +#log-append /log/openvpn.log # Status -status log/status 30 +#status /log/status 30 status-version 2 # Client config directory -client-config-dir openvpn/ccd +client-config-dir /config/openvpn/ccd # Certificate revocation list -crl-verify pki/crl.pem +crl-verify /config/pki/crl.pem # Include configs -config include-server.conf +config /config/openvpn/include-conf.conf diff --git a/root/etc/cont-finish.d/60-network b/root/etc/cont-finish.d/60-network deleted file mode 100755 index 4f050d5..0000000 --- a/root/etc/cont-finish.d/60-network +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/with-contenv bash - -source /app/lib/settings - -# -# Network setup -# - -# Delete tunnel interface (if not persistant) -intTunExists -TUNE=$? -intPersistant -PERINT=$? -if [ $TUNE -eq 0 ] && [ $PERINT -eq 0 ]; then # TUN interface exists & !persistant - echo "Removing tun0 interface" - openvpn --rmtun --dev tun0 -fi \ No newline at end of file diff --git a/root/etc/cont-finish.d/60-network.sh b/root/etc/cont-finish.d/60-network.sh new file mode 100755 index 0000000..ee8d03d --- /dev/null +++ b/root/etc/cont-finish.d/60-network.sh @@ -0,0 +1,11 @@ +#!/usr/bin/with-contenv bash + +# +# Network setup +# + +# Delete tunnel interface (if not persistant) +if [ -n "$(cat /proc/net/dev | grep tun0)" ] && { [ -z "$PERSISTENT_INTERFACE" ] || [ "$PERSISTENT_INTERFACE" != "true" ]; }; then + echo "Removing tun0 interface" + openvpn --rmtun --dev tun0 +fi \ No newline at end of file diff --git a/root/etc/cont-finish.d/99-custom_finish b/root/etc/cont-finish.d/99-custom_finish.sh old mode 100644 new mode 100755 similarity index 100% rename from root/etc/cont-finish.d/99-custom_finish rename to root/etc/cont-finish.d/99-custom_finish.sh diff --git a/root/etc/cont-init.d/20-env b/root/etc/cont-init.d/20-env deleted file mode 100644 index 08ab6df..0000000 --- a/root/etc/cont-init.d/20-env +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/with-contenv bash - -# -# Display environment variables -# - -# Display variables for troubleshooting -echo -e "Variables set:\\n\ -PUID=${PUID}\\n\ -PGID=${PGID}\\n\ -EASYRSA=${EASYRSA}\\n\ -EASYRSA_OPENSSL=${EASYRSA_OPENSSL}\\n\ -EASYRSA_SSL_CONF=${EASYRSA_SSL_CONF}\\n\ -EASYRSA_PKI=${EASYRSA_PKI}\\n\ -EASYRSA_DN=${EASYRSA_DN}\\n\ -EASYRSA_REQ_COUNTRY=${EASYRSA_REQ_COUNTRY}\\n\ -EASYRSA_REQ_PROVINCE=${EASYRSA_REQ_PROVINCE}\\n\ -EASYRSA_REQ_CITY=${EASYRSA_REQ_CITY}\\n\ -EASYRSA_REQ_ORG=${EASYRSA_REQ_ORG}\\n\ -EASYRSA_REQ_EMAIL=${EASYRSA_REQ_EMAIL}\\n\ -EASYRSA_REQ_OU=${EASYRSA_REQ_OU}\\n\ -EASYRSA_KEY_SIZE=${EASYRSA_KEY_SIZE}\\n\ -EASYRSA_ALGO=${EASYRSA_ALGO}\\n\ -EASYRSA_CURVE=${EASYRSA_CURVE}\\n\ -EASYRSA_EC_DIR=${EASYRSA_EC_DIR}\\n\ -EASYRSA_CA_EXPIRE=${EASYRSA_CA_EXPIRE}\\n\ -EASYRSA_CERT_EXPIRE=${EASYRSA_CERT_EXPIRE}\\n\ -EASYRSA_CRL_DAYS=${EASYRSA_CRL_DAYS}\\n\ -EASYRSA_NS_SUPPORT=${EASYRSA_NS_SUPPORT}\\n\ -EASYRSA_NS_COMMENT=${EASYRSA_NS_COMMENT}\\n\ -EASYRSA_TEMP_FILE=${EASYRSA_TEMP_FILE}\\n\ -EASYRSA_REQ_CN=${EASYRSA_REQ_CN}\\n\ -EASYRSA_DIGEST=${EASYRSA_DIGEST}\\n\ -EASYRSA_BATCH=${EASYRSA_BATCH}\\n\ -OVPN_PERINT=${OVPN_PERINT}\\n\ -" diff --git a/root/etc/cont-init.d/50-config b/root/etc/cont-init.d/50-config deleted file mode 100644 index abb8d48..0000000 --- a/root/etc/cont-init.d/50-config +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/with-contenv bash - -# File which indicates that full init was already done before -FLAG_FILE=/config/donotdelete - -HOOKS_DIR=(auth client-connect client-disconnect finish down init learn-address route-pre-down route-up up tls-verify) -OVPN_DIR=(ccd client server) - -FIRST_SETUP=0 - -# Check if we need initial setup -if [ ! -e "$FLAG_FILE" ]; then - FIRST_SETUP=1 - - # Full setup is required - touch $FLAG_FILE - - # Copy defaults to config (if not exist) - echo "Copying defaults" - cp -R -u /defaults/* /config -fi - -# Setup log -if [ ! -e "/config/log" ]; then - echo "Creating /config/log" - mkdir -p /config/log - touch /config/log/openvpn.log -fi - -# Setup hooks -if [ ! -e "/config/hooks" ]; then - echo "Creating /config/hooks" - mkdir -p /config/hooks -fi -# Check for each hook if exists -for h in "${HOOKS_DIR[@]}"; do - if [ ! -e "/config/hooks/$h" ]; then - echo "Creating /config/hooks/$h" - mkdir /config/hooks/$h - fi -done - -# Setup openvpn -if [ ! -e "/config/openvpn" ]; then - echo "Creating /config/openvpn" - mkdir -p /config/openvpn -fi -# Check for each dir if exists -for h in ${OVPN_DIR[@]} -do - if [ ! -e "/config/openvpn/$h" ]; then - echo "Creating /config/openvpn/$h" - mkdir /config/openvpn/$h - fi -done - -# Setup easy-rsa -if [ ! -e "/config/ssl" ]; then - echo "Setting up /config/ssl" - mkdir -p /config/ssl - #cp -R -u $EASYRSA/openssl-easyrsa.cnf $EASYRSA_SSL_CONF - cp -R -u $EASYRSA/vars.example /config/ssl/vars -else - #if [ ! -e "$EASYRSA_SSL_CONF" ]; then - # cp -R -u $EASYRSA/openssl-easyrsa.cnf $EASYRSA_SSL_CONF - #fi - if [ ! -e "/config/ssl/vars" ]; then - cp -R -u $EASYRSA/vars.example /config/ssl/vars - fi -fi -if [ -e "/config/pki" ]; then - # Create CRL file, if it can - if [ ! -e "/config/pki/crl.pem" ]; then - touch /config/pki/crl.pem - fi -fi - -# Setup module -if [ ! -e "/config/module" ]; then - echo "Creating /config/module" - mkdir /config/module -fi - -# Setup backup -if [ ! -e "/config/backup" ]; then - mkdir /config/backup -fi - -# Setup tmp -if [ ! -e "/config/tmp" ]; then - mkdir /config/tmp -fi - -# Build include-server.conf -INC_SERVER_FILE=/config/include-server.conf -echo "#" > $INC_SERVER_FILE -echo "# DO NOT EDIT" >> $INC_SERVER_FILE -echo "# Autogenerated file, based on /config/openvpn/server" >> $INC_SERVER_FILE -echo "#" >> $INC_SERVER_FILE -echo "" >> $INC_SERVER_FILE - -for file in /config/openvpn/server/*.conf -do - [ -e "$file" ] || continue - - echo "config $file" >> $INC_SERVER_FILE -done - -# Change permissions only on initial setup -if [ $FIRST_SETUP -eq 1 ]; then - echo "Fixing permissions" - - # Set permissions - chown -R abc:abc /config -fi \ No newline at end of file diff --git a/root/etc/cont-init.d/50-setup.sh b/root/etc/cont-init.d/50-setup.sh new file mode 100755 index 0000000..820f02f --- /dev/null +++ b/root/etc/cont-init.d/50-setup.sh @@ -0,0 +1,83 @@ +#!/usr/bin/with-contenv bash + +# +# Setup /config directory +# + +# Setup backup +if [ ! -e "/config/backup" ]; then + mkdir /config/backup + chown abc:abc /config/backup +fi + +# +# Setup openvpn directory +# + +if [ ! -d "/config/openvpn" ]; then + echo "Creating /config/openvpn" + mkdir -p /config/openvpn + chown abc:abc /config/openvpn +fi + +# Check directories inside openvpn directory +OVPN_DIR=(ccd client config hooks) +for h in ${OVPN_DIR[@]} +do + if [ ! -d "/config/openvpn/$h" ]; then + echo "Creating /config/openvpn/$h" + mkdir /config/openvpn/$h + chown abc:abc /config/openvpn/$h + fi +done + +# Check hook directories +HOOKS_DIR=( \ + auth \ + client-connect \ + client-disconnect \ + down \ + finish \ + init \ + learn-address \ + route-pre-down \ + route-up \ + tls-verify \ + up \ + ) +for h in "${HOOKS_DIR[@]}"; do + if [ ! -d "/config/openvpn/hooks/$h" ]; then + echo "Creating /config/openvpn/hooks/$h" + mkdir /config/openvpn/hooks/$h + chown abc:abc /config/openvpn/hooks/$h + fi +done + +# +# Setup EasyRSA +# + +if [ -d "/config/pki" ]; then + # Create CRL file, if it can + if [ ! -f "/config/pki/crl.pem" ]; then + touch /config/pki/crl.pem + fi +fi + +if [ ! -d "/config/ssl" ]; then + echo "Setting up /config/ssl" + mkdir -p /config/ssl + chown abc:abc /config/ssl +fi + +if [ ! -e "$EASYRSA_VARS_FILE" ]; then + #cp -R -u $EASYRSA/openssl-easyrsa.cnf $EASYRSA_SSL_CONF + cp -R -u $EASYRSA/vars.example $EASYRSA_VARS_FILE + chown abc:abc $EASYRSA_VARS_FILE +fi + +# Setup tmp +if [ ! -e "/config/tmp" ]; then + mkdir /config/tmp + chown abc:abc /config/tmp +fi diff --git a/root/etc/cont-init.d/60-network b/root/etc/cont-init.d/60-network deleted file mode 100644 index c435056..0000000 --- a/root/etc/cont-init.d/60-network +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/with-contenv bash - -source /app/lib/settings - -# -# Network setup -# - -# -# Setup tunnel driver -# -# @see https://help.skysilk.com/support/solutions/articles/9000136471-how-to-enable-tun-tap-on-linux-vps-with-skysilk -# @see https://community.openvpn.net/openvpn/wiki/UnprivilegedUser -# @see https://unix.stackexchange.com/questions/18215/which-user-group-can-use-the-tap-net-device -# -if [ ! -d "/dev/net" ]; then - echo "Creating /dev/net" - mkdir -p /dev/net -fi -if [ ! -c "/dev/net/tun" ]; then - mknod /dev/net/tun c 10 200 - chmod 666 /dev/net/tun -fi - -# Setup tun0 as tunnel interface -intTunExists -TUNE=$? -intPersistant -PERINT=$? -if [ $TUNE -eq 0 ] && [ $PERINT -eq 0 ]; then # TUN interface exists & !persistant - echo "Removing tun0 interface" - openvpn --rmtun --dev tun0 -fi -if [ $TUNE -eq 1 ]; then # TUN interface !exist - echo "Creating tun0 interface" - openvpn --mktun --dev tun0 --dev-type tun --user abc --group abc -fi \ No newline at end of file diff --git a/root/etc/cont-init.d/60-network.sh b/root/etc/cont-init.d/60-network.sh new file mode 100755 index 0000000..37dcf20 --- /dev/null +++ b/root/etc/cont-init.d/60-network.sh @@ -0,0 +1,31 @@ +#!/usr/bin/with-contenv bash + +# +# Setup tunnel driver +# +# @see https://help.skysilk.com/support/solutions/articles/9000136471-how-to-enable-tun-tap-on-linux-vps-with-skysilk +# @see https://community.openvpn.net/openvpn/wiki/UnprivilegedUser +# @see https://unix.stackexchange.com/questions/18215/which-user-group-can-use-the-tap-net-device +# + +if [ ! -d "/dev/net" ]; then + echo "Creating /dev/net" + mkdir -p /dev/net +fi + +if [ ! -c "/dev/net/tun" ]; then + mknod /dev/net/tun c 10 200 + chmod 666 /dev/net/tun +fi + +# Remove existing interface if not persistent interface selected +if [ -n "$(cat /proc/net/dev | grep tun0)" ] && { [ -z "$PERSISTENT_INTERFACE" ] || [ "$PERSISTENT_INTERFACE" != "true" ]; }; then + echo "Removing tun0 interface" + openvpn --rmtun --dev tun0 +fi + +# Create tunnel interface +if [ -z "$(cat /proc/net/dev | grep tun0)" ]; then + echo "Creating tun0 interface" + openvpn --mktun --dev tun0 --dev-type tun --user abc --group abc +fi diff --git a/root/etc/cont-init.d/70-config.sh b/root/etc/cont-init.d/70-config.sh new file mode 100755 index 0000000..acd078d --- /dev/null +++ b/root/etc/cont-init.d/70-config.sh @@ -0,0 +1,23 @@ +#!/usr/bin/with-contenv bash + +# +# Link OpenVPN configs +# + +LINK_FILE=/config/openvpn/include-conf.conf + +# Build link file +echo "#" > $LINK_FILE +echo "# DO NOT EDIT" >> $LINK_FILE +echo "# Autogenerated file, based on /config/openvpn/config" >> $LINK_FILE +echo "#" >> $LINK_FILE +echo "" >> $LINK_FILE + +for file in /config/openvpn/config/* +do + [ -e "$file" ] || continue + + echo "config $file" >> $LINK_FILE +done + +chown abc:abc $LINK_FILE diff --git a/root/etc/cont-init.d/99-custom_init b/root/etc/cont-init.d/99-custom_init.sh old mode 100644 new mode 100755 similarity index 100% rename from root/etc/cont-init.d/99-custom_init rename to root/etc/cont-init.d/99-custom_init.sh diff --git a/root/etc/logrotate.d/openvpn b/root/etc/logrotate.d/openvpn deleted file mode 100644 index 61c721f..0000000 --- a/root/etc/logrotate.d/openvpn +++ /dev/null @@ -1,9 +0,0 @@ -/config/log/openvpn.log { - weekly - rotate 7 - missingok - compress - delaycompress - nodateext - su abc abc -} \ No newline at end of file diff --git a/root/etc/services.d/openvpn/finish b/root/etc/services.d/openvpn/finish new file mode 100644 index 0000000..4134391 --- /dev/null +++ b/root/etc/services.d/openvpn/finish @@ -0,0 +1,9 @@ +#!/usr/bin/with-contenv sh + +# +# Handle service failiure +# + +if [ "$FAIL_MODE" == "hard" ]; then + exec s6-svscanctl -t /var/run/s6/services +fi diff --git a/root/etc/services.d/openvpn/run b/root/etc/services.d/openvpn/run index 12834ea..3214e75 100644 --- a/root/etc/services.d/openvpn/run +++ b/root/etc/services.d/openvpn/run @@ -1,17 +1,31 @@ #!/usr/bin/with-contenv bash -CONFIGS=$(ls -1 /config/openvpn/server | wc -l) # Get number of files in /config/openvpn/server +if [ ! -d "/config/openvpn" ] || [ ! -f "/config/openvpn/system.conf" ]; then + echo "System configuration is missing" + if [ "$FAIL_MODE" != "hard" ]; then + # Do nothing until container restart + while true + do + sleep 3600 + done + fi + exit 1 +fi + +CONFIGS=$(ls -1 /config/openvpn/config | wc -l) # Get number of files if [ $CONFIGS -gt 0 ]; then - # Run OpenVPN server only if configs are present - echo "Running OpenVPN ..." - sudo -E -u abc openvpn --cd /config --config ${OVPN_RUN} + # Run OpenVPN only if configs are present + echo "Running OpenVPN ..." + sudo -E -u abc openvpn --config /config/openvpn/system.conf else - # No OpenVPN config present - echo "No OpenVPN config present" - + # No OpenVPN config present + echo "No OpenVPN config present" + if [ "$FAIL_MODE" != "hard" ]; then # Do nothing until container restart while true do - sleep 3600 + sleep 3600 done + fi + exit 1 fi \ No newline at end of file diff --git a/root/usr/local/bin/ovpn b/root/usr/local/bin/ovpn new file mode 100755 index 0000000..3dd8792 --- /dev/null +++ b/root/usr/local/bin/ovpn @@ -0,0 +1,41 @@ +#!/bin/bash + +# +# OpenVPN utils +# + +function usage() { + echo "Usage: ovpn COMMAND [ARGS..]" + echo "" + echo "Commands:" + echo " backup # Creates backup of configuration files" + echo " client [add|ovpn|ovpnp|ban|revoke|remove|delete|help] [NAME] [nopass] # Client manipulation" + echo " disconf # Deletes active config" + echo " enconf EXAMPLE_CONFIG_NAME [wizard args] # Enable example config" + echo " pki [init|remove|delete] # Public Key Intrastructure" + echo " restore ARCHIVE_FILE # Restores backup" +} + +if [ $# -lt 1 ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + exit 1 +fi + +# Run selected command +cmd="$(echo $1 | tr '[:upper:]' '[:lower:]')" # Convert to lowercase +if [ "$cmd" == "backup" ]; then + ovpn_backup ${@:2} +elif [ "$cmd" == "client" ]; then + ovpn_client ${@:2} +elif [ "$cmd" == "disconf" ]; then + ovpn_disconf ${@:2} +elif [ "$cmd" == "enconf" ]; then + ovpn_enconf ${@:2} +elif [ "$cmd" == "pki" ]; then + ovpn_pki ${@:2} +elif [ "$cmd" == "restore"]; then + ovpn_restore ${@:2} +else + usage + exit 1 +fi \ No newline at end of file diff --git a/root/usr/local/bin/ovpn_backup b/root/usr/local/bin/ovpn_backup new file mode 100755 index 0000000..bfb7e0a --- /dev/null +++ b/root/usr/local/bin/ovpn_backup @@ -0,0 +1,15 @@ +#!/bin/bash + +# +# Backup script +# +# Backups to /config/backup +# + +BACKUP_DIRS=(openvpn pki ssl) +ARCHIVE_NAME="/config/backup/ovpn_backup_$(date +%Y%m%d%H%M%S).tar.gz" + +cd /config && tar cfvz $ARCHIVE_NAME ${BACKUP_DIRS[@]} +if [ "$USER" != "abc" ]; then + chown abc:abc $ARCHIVE_NAME # Fix backup archive permissions +fi \ No newline at end of file diff --git a/root/usr/local/bin/ovpn_client b/root/usr/local/bin/ovpn_client new file mode 100755 index 0000000..c9d2eb4 --- /dev/null +++ b/root/usr/local/bin/ovpn_client @@ -0,0 +1,156 @@ +#!/bin/bash + +# +# OpenVPN client configuration generator +# + +# User permission fix +if [ "$USER" != "abc" ]; then + RUNAS="sudo -E -u abc" +else + RUNAS="" +fi + +function usage() { + echo "Usage: ovpn_client COMMAND [ARGS]" + echo "" + echo "Commands:" + echo " add [NAME [nopass]] # Creates certificates for client" + echo " ovpn NAME # Generates .ovpn file (saves to tmp)" + echo " ovpnp NAME # Generates .ovpn file (prints it to the screen)" + echo " revoke|ban NAME # Adds client to CRL" + echo " remove|delete NAME # Removes client config" +} + +# Invalid command / help +if [ $# -lt 1 ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + exit 1 +fi + +function build_ovpn() { + if [ $# -lt 1 ]; then + return 1 + fi + + local OVPN_FILE="/config/tmp/$1.ovpn" + + # Delete existing + if [ -f "$OVPN_FILE" ]; then + read -p ".ovpn file already exsist for $1, are you sure to overwrite it? [y/N]" decision + decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + if [ "$decision" != "y" ] && [ "$decision" == "yes" ]; then + exit 0 # Don't overwrite + fi + rm $OVPN_FILE + fi + + # Build .ovpn from client config files + for file in /config/openvpn/client/*.conf + do + [ -e "$file" ] || continue + cat $file >> $OVPN_FILE + done + + # Find which security mechanism is openvpn using + local crypto="" + for srv_file in /config/openvpn/config/*.conf + do + crypto=`cat $srv_file | grep -E "^\\s*(secret|tls-auth|tls-crypt).*$" | cut -d" " -f1` + if [ -n "$crypto" ]; then + break + fi + done + + # Add ca.crt + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/ca.crt >> $OVPN_FILE + echo "" >> $OVPN_FILE + echo "" >> $OVPN_FILE + + # Add client cert + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/issued/$1.crt >> $OVPN_FILE + echo "" >> $OVPN_FILE + + # Add client key + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/private/$1.key >> $OVPN_FILE + echo "" >> $OVPN_FILE + + # Add security mechanism specific key + if [ "$crypto" == "tls-crypt" ]; then + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/ta.key >> $OVPN_FILE + echo "" >> $OVPN_FILE + elif [ "$crypto" == "tls-auth" ]; then + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/ta.key >> $OVPN_FILE + echo "" >> $OVPN_FILE + elif [ "$crypto" == "secret" ]; then + echo "" >> $OVPN_FILE + cat $EASYRSA_PKI/secret.key >> $OVPN_FILE + echo "" >> $OVPN_FILE + fi + + chown abc:abc $OVPN_FILE + + if [ $# -gt 1 ] && [ "$2" == "print" ]; then + cat $OVPN_FILE + fi +} + +if [ "$1" == "add" ]; then + if [ $# -eq 1 ]; then # No additional args + read -p "Common name:" commonName + read -p "Password protect [Y/n]: " decision + decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + if [ "$decision" == "n" ] || [ "$decision" == "no" ]; then + $RUNAS easyrsa gen-req $commonName nopass + else + $RUNAS easyrsa gen-req $commonName + fi + $RUNAS easyrsa sign-req client $commonName + else + # Just build cert + $RUNAS easyrsa gen-req ${@:2} + $RUNAS easyrsa sign-req client ${@:2} + fi +elif [ "$1" == "ovpn" ]; then + if [ $# -gt 1 ]; then + build_ovpn $2 + else # Common name missing + usage + exit 1 + fi +elif [ "$1" == "ovpnp" ]; then + if [ $# -gt 1 ]; then + build_ovpn $2 print + else # Common name missing + usage + exit 1 + fi +elif [ "$1" = "ban" ] || [ "$1" = "revoke" ] ; then + if [ $# -gt 1 ]; then + $RUNAS easyrsa revoke ${@:2} + $RUNAS easyrsa gen-crl + else + usage + exit 1 + fi +elif [ "$1" = "remove" ] || [ "$1" = "delete"]; then + if [ $# -gt 1 ]; then + read -p "Are you sure to remove certs for $2 ? [y/N]: " decision + decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + if [ "$decision" == "y" ] || [ "$decision" == "yes" ]; then + rm $EASYRSA_PKI/issued/$1.crt + rm $EASYRSA_PKI/private/$1.key + fi + else + usage + exit 1 + fi +else + usage + exit 1 +fi diff --git a/root/usr/local/bin/ovpn_disconf b/root/usr/local/bin/ovpn_disconf new file mode 100755 index 0000000..c37c75d --- /dev/null +++ b/root/usr/local/bin/ovpn_disconf @@ -0,0 +1,40 @@ +#!/bin/bash + +# +# Disables OpenVPN config +# WARNING: This deletes active OpenVPN config & active hooks +# + +# Check if OpenVPN config directory exsist +config_path="/config/openvpn" +if [ ! -d "$config_path" ]; then + exit 0 +fi + +# Display notice +echo "This script will clear your configuration (whole openvpn directory)." +echo "Please make sure that you backed up you config and active hooks." + +# Make sure that user understands +read -p "Are you sure, you want to delete active config and hooks ? [y/N]:" decision +decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + +# Check if operation aborted +if [ "$decision" != "y" ] && [ "$decision" != "yes" ]; then + exit 0 +fi + +# Delete config +if [ -d "$config_path/config" ]; then + rm -rf $config_path/config/* +fi + +# Delete client config +if [ -d "$config_path/client" ]; then + rm -rf $config_path/client/* +fi + +# Delete hook scripts +if [ -d "$config_path/hooks" ]; then + rm -rf $config_path/hooks/*/* +fi diff --git a/root/usr/local/bin/ovpn_enconf b/root/usr/local/bin/ovpn_enconf new file mode 100755 index 0000000..e03bea7 --- /dev/null +++ b/root/usr/local/bin/ovpn_enconf @@ -0,0 +1,109 @@ +#!/bin/bash + +# +# Enables OpenVPN config example +# + +# User permission fix +if [ "$USER" != "abc" ]; then + RUNAS="sudo -E -u abc" +else + RUNAS="" +fi + +function usage() { + echo "Usage: ovpn_enconf CONFIG_NAME [wizard args...]" + echo "" + echo "Configs:" + local identifiers=() # Which identifiers we already printed out + + # Go through all identifiers + for folder in /defaults/example/config/* + do + [ -d "$folder" ] || continue + + local folder_name="$(echo $folder | sed -E 's/^\/.*\/(.*)$/\1/')" + + # Check if we already printed out that identifer + local found=0 + for i in "$identifiers" + do + if [ "$i" = "$folder_name" ]; then + found=1 + break + fi + done + if [ $found -eq 0 ]; then + # Print out new identifier + echo "$folder_name" + identifiers=($identifiers $folder_name) + fi + done +} + +if [ $# -lt 1 ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + exit 1 +fi + +# Get wanted config name +config_name=$1 +config_path=/defaults/example/config/$config_name + +# Check if config exists +if [ ! -d $config_path ]; then + echo "Config does not exist" + exit 2 +fi + + +# Configure copy destination +if [ -f "$config_path/wizard" ] && [ -x "$config_path/wizard" ]; then + tmp_path=/tmp/wizard + + # Delete existing tmp directory + if [ -d "$tmp_path" ]; then + rm -rf $tmp_path + fi + + # Copy config to temporary folder so it can be modified + $RUNAS cp -r $config_path $tmp_path + + # Run wizard (with temporary path) + currdir="$(pwd)" + cd $tmp_path + $RUNAS $tmp_path/wizard "$tmp_path" ${@:2} + exit_code=$? + cd $currdir + + # If wizard exists with code other than 0, return error + if [ $exit_code -ne 0 ]; then + echo "Error while executing wizard" + exit $exit_code + fi + + # Copy wizard finished files + COPY_DIRS=(ccd client config hooks) + for dir in "${COPY_DIRS[@]}" + do + [ -d "$tmp_path/$dir" ] || continue + $RUNAS cp -r $tmp_path/$dir/* /config/openvpn/$dir/ + done + + # Remove temporary directory + rm -rf $tmp_path +else + # Directly copy files + # Copy wizard finished files + COPY_DIRS=(ccd client config hooks) + for dir in "${COPY_DIRS[@]}" + do + [ -d "$config_path/$dir" ] || continue + $RUNAS cp -r $config_path/$dir/* /config/openvpn/$dir/ + done + + # Wizard not available + echo "Sorry, wizard not available for this config" + echo "" + echo "Please edit config files in /config/openvpn to suite your needs" +fi diff --git a/root/usr/local/bin/ovpn_pki b/root/usr/local/bin/ovpn_pki new file mode 100755 index 0000000..ca4acd9 --- /dev/null +++ b/root/usr/local/bin/ovpn_pki @@ -0,0 +1,86 @@ +#!/bin/bash + +# +# OpenVPN PKI configuration script +# +# @see https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto +# @see https://forums.openvpn.net/viewtopic.php?t=20837 +# @see https://securitronlinux.com/bejiitaswrath/how-to-create-keys-with-easy-rsa-without-a-password-prompt/ +# +# + +# User permission fix +if [ "$USER" != "abc" ]; then + RUNAS="sudo -E -u abc" +else + RUNAS="" +fi + +function usage() { + echo "Usage: ovpn_pki COMMAND" + echo "" + echo "Commands:" + echo " delete|remove # Removes PKI" + echo " init [nopass] # Init PKI" +} + +if [ $# -lt 1 ] || [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + exit 1 +fi + + +# +# Init CA +# +function init() { + if [ -d "$EASYRSA_PKI" ]; then + read -p "PKI directory already exists. You will LOSE all files in your PKI. Are you SURE to init PKI again ? [y/N]: " decission + decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + if [ "$decision" != "y"] && [ "$decision" != "yes" ]; then + exit 0 + fi + rm -rf $EASYRSA_PKI + fi + + # Init PKI + $RUNAS easyrsa init-pki + + # Build dh.pem + $RUNAS easyrsa gen-dh + + # Build CA + echo "Now it will build CA files for issuing new certifiactes" + echo "Please protect ca.key with secure password (used for signing new certs)" + echo "ca.key is needed only for signing new certificates, not for OpenVPN to work" + $RUNAS easyrsa build-ca ${@:1} + + # Build server key + $RUNAS easyrsa build-server-full server nopass + $RUNAS easyrsa sign-req server server + rm $EASYRSA_PKI/reqs/server.req + + # Generate ta.key (for tls-auth,tls-crypt) + $RUNAS openvpn --genkey --secret $EASYRSA_PKI/ta.key + + # Generate CRL + $RUNAS easyrsa gen-crl +} + +cmd="$(echo $1 | tr '[:upper:]' '[:lower:]')" +if [ "$cmd" == "init" ]; then + init ${@:2} +elif [ "$cmd" == "remove"] || [ "$cmd" == "delete" ]; then + if [ ! -d "$EASYRSA_PKI" ]; then + exit 0 + fi + read -p "Are you sure to remove PKI ? [y/N]: " decision + decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + # Check if operation aborted + if [ "$decision" == "y" ] && [ "$decision" == "yes" ]; then + rm -rf $EASYRSA_PKI + fi +else + usage + exit 1 +fi diff --git a/root/usr/local/bin/ovpn_restore b/root/usr/local/bin/ovpn_restore new file mode 100755 index 0000000..4445c94 --- /dev/null +++ b/root/usr/local/bin/ovpn_restore @@ -0,0 +1,24 @@ +#!/bin/bash + +# +# Restore script +# +# Restores config from archive +# + +# User permission fix +if [ "$USER" != "abc" ]; then + RUNAS="sudo -E -u abc" +else + RUNAS="" +fi + +read -p "Make sure to disable current config (ovpn disconf) and remove current pki (ovpn pki remove), before you restore config. Done ? [Y/n]: " decision +decision="$(echo $decision | tr '[:upper:]' '[:lower:]')" # Convert to lowercase + +# Check if operation aborted +if [ "$decision" == "n" ] && [ "$decision" == "no" ]; then + exit 0 +fi + +$RUNAS tar -fvx $1 -C /config diff --git a/root/usr/local/bin/run_hooks b/root/usr/local/bin/run_hooks new file mode 100755 index 0000000..460b67a --- /dev/null +++ b/root/usr/local/bin/run_hooks @@ -0,0 +1,52 @@ +#!/bin/bash + +# +# Run hook scripts +# + +function usage() { + echo "Usage: run_hooks HOOK_NAME [ARGS]" + echo "" + echo "Hooks:" + echo " auth On OpenVPN client authentication" + echo " client-connect On OpenVPN client connected" + echo " client-disconnect On OpenVPN client disconnected" + echo " finish On container shutdown" + echo " init On container power on" + echo " learn-address Client Address & Routes validation" + echo " down Before/After TUN interface closed" + echo " route-up After routes are added" + echo " route-pre-down Before routes are removed" + echo " tls-verify On OpenVPN client certificate verificaton" + echo " up After TUN interface opened" +} + +# Check if hook name is set +if [ -z "$1" ]; then + usage + exit 1 +fi + +# Check if hook directory exist +if [ ! -d "/config/openvpn/hooks/$1" ]; then + echo "Hook /config/openvpn/hooks/$1 directory does not exist" + exit 2 +fi + +# Run each script and check for return code +for script in /config/openvpn/hooks/$1/* +do + { [ -f "$script" ] && [ -x "$script" ]; } || continue + + # Run script and pass additional args to hooks + echo "Executing hook: $script" + $script ${@:2} + + # Check for error while executing script + exit_status=$? + if [ $exit_status -ne 0 ]; then + # In case one of the hook files fails, everything fails + echo "$script exited with $exit_status." + exit $exit_status + fi +done diff --git a/root/usr/local/sbin/ovpn-ip b/root/usr/local/sbin/ovpn-ip old mode 100644 new mode 100755 diff --git a/root/usr/local/sbin/ovpn-ip6tables b/root/usr/local/sbin/ovpn-ip6tables old mode 100644 new mode 100755 diff --git a/root/usr/local/sbin/ovpn-iptables b/root/usr/local/sbin/ovpn-iptables old mode 100644 new mode 100755 diff --git a/root/usr/local/sbin/ovpn-route b/root/usr/local/sbin/ovpn-route old mode 100644 new mode 100755