initial commit
This commit is contained in:
parent
2e5602bbfc
commit
bef0f7262b
|
|
@ -0,0 +1,43 @@
|
||||||
|
FROM alpine:edge
|
||||||
|
|
||||||
|
LABEL maintainer="Kirillius Labutin <labutin.kirillius@gmail.com>"
|
||||||
|
|
||||||
|
ENV container=docker
|
||||||
|
|
||||||
|
RUN apk --update add openrc openvpn frr php easy-rsa nano
|
||||||
|
|
||||||
|
RUN echo 'rc_cgroups_enabled="NO"' >> /etc/rc.conf
|
||||||
|
|
||||||
|
RUN echo 'rc_provide="loopback net"' >> /etc/rc.conf
|
||||||
|
|
||||||
|
RUN rm /etc/init.d/loopback /etc/init.d/networking /etc/init.d/machine-id /etc/init.d/hwdrivers
|
||||||
|
|
||||||
|
RUN openrc
|
||||||
|
|
||||||
|
RUN ln -s /data/pki /etc/openvpn/keys
|
||||||
|
|
||||||
|
COPY connect.php /etc/openvpn/connect.php
|
||||||
|
|
||||||
|
RUN chmod +x /etc/openvpn/connect.php
|
||||||
|
|
||||||
|
COPY openvpn.conf /data/openvpn.conf
|
||||||
|
|
||||||
|
RUN ln -s /data/openvpn.conf /etc/openvpn/openvpn.conf
|
||||||
|
|
||||||
|
COPY vars /usr/share/easy-rsa
|
||||||
|
|
||||||
|
COPY client-config-template.conf /data/client-config-template.conf
|
||||||
|
|
||||||
|
COPY build-client-config.php /usr/bin/build-client-config
|
||||||
|
|
||||||
|
RUN sed -i 's/^tty/#&/' /etc/inittab
|
||||||
|
|
||||||
|
RUN chmod +x /usr/bin/build-client-config
|
||||||
|
|
||||||
|
RUN mv /etc/frr /data/frr
|
||||||
|
|
||||||
|
RUN ln -s /data/frr /etc/frr
|
||||||
|
|
||||||
|
RUN sed -i 's#/etc/frr#/data/frr#g' /etc/init.d/frr
|
||||||
|
|
||||||
|
ENTRYPOINT ["/sbin/init"]
|
||||||
48
README.md
48
README.md
|
|
@ -1,2 +1,48 @@
|
||||||
# openvpn-frr-template
|
# 1. Init RSA
|
||||||
|
```shell
|
||||||
|
cd /usr/share/easy-rsa
|
||||||
|
./easyrsa clean-all
|
||||||
|
./easyrsa init-pki
|
||||||
|
./easyrsa build-ca nopass
|
||||||
|
./easyrsa build-server-full server nopass
|
||||||
|
./easyrsa gen-dh
|
||||||
|
```
|
||||||
|
|
||||||
|
# 2. Create user certs
|
||||||
|
```shell
|
||||||
|
cd /usr/share/easy-rsa
|
||||||
|
./easyrsa build-client-full USERNAME nopass
|
||||||
|
```
|
||||||
|
|
||||||
|
# 3. Configure server
|
||||||
|
Preconfigured example is here:
|
||||||
|
```shell
|
||||||
|
nano /data/openvpn.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
# 4. Enable routing protocols
|
||||||
|
```shell
|
||||||
|
nano /data/frr/daemons
|
||||||
|
```
|
||||||
|
|
||||||
|
# 5. Enable services autostart
|
||||||
|
```shell
|
||||||
|
rc-update add frr
|
||||||
|
rc-update add openvpn
|
||||||
|
```
|
||||||
|
|
||||||
|
# 6. Start services
|
||||||
|
```shell
|
||||||
|
rc-service frr start
|
||||||
|
rc-service openvpn start
|
||||||
|
```
|
||||||
|
|
||||||
|
# 7. Configure router
|
||||||
|
```shell
|
||||||
|
vtysh
|
||||||
|
```
|
||||||
|
|
||||||
|
# 8. Get client config file
|
||||||
|
```shell
|
||||||
|
build-client-config USERNAME
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
if (!isset($argv[1])) {
|
||||||
|
die("Client name is not specified!\n");
|
||||||
|
}
|
||||||
|
function readFileOrDie($file)
|
||||||
|
{
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
die("File " . $file . " not found!\n");
|
||||||
|
}
|
||||||
|
return file_get_contents($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrap($what, $tag)
|
||||||
|
{
|
||||||
|
return "<" . $tag . ">" . $what . "</" . $tag . ">\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$clientName = $argv[1];
|
||||||
|
$template = readFileOrDie("/data/client-config-template.conf");
|
||||||
|
$template .= "\n";
|
||||||
|
$template .= wrap(readFileOrDie("/data/pki/issued/" . $clientName . ".crt"), "cert");
|
||||||
|
$template .= wrap(readFileOrDie("/data/pki/ca.crt"), "ca");
|
||||||
|
$template .= wrap(readFileOrDie("/data/pki/private/" . $clientName . ".key"), "key");
|
||||||
|
echo "\n\n\nYour config is: \n ================================\n\n" . $template . "\n\n===============================\n";
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
client
|
||||||
|
dev tun
|
||||||
|
proto udp
|
||||||
|
remote YOURSERVER 1194
|
||||||
|
resolv-retry infinite
|
||||||
|
nobind
|
||||||
|
ns-cert-type server
|
||||||
|
persist-key
|
||||||
|
persist-tun
|
||||||
|
verb 3
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
function is_subnet_overlaps($subnet, $candidate)
|
||||||
|
{
|
||||||
|
$parts = explode("/", $subnet);
|
||||||
|
$prefix = $parts[1];
|
||||||
|
$subnet_first = ip2long($parts[0]);
|
||||||
|
$candidate_prefix = explode("/", $candidate)[1];
|
||||||
|
$count = pow(2, 32 - (int)$prefix);
|
||||||
|
$subnet_last = $subnet_first + $count - 1;
|
||||||
|
$test_ip = ip2long(explode("/", $candidate)[0]);
|
||||||
|
return $test_ip >= $subnet_first and $test_ip <= $subnet_last and $candidate_prefix > $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RoutingTableReader
|
||||||
|
{
|
||||||
|
private $routes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getRoutes(): array
|
||||||
|
{
|
||||||
|
return $this->routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$result = @shell_exec("ip --json route show");
|
||||||
|
if (!$result) {
|
||||||
|
throw new RuntimeException("Failed to read routing table");
|
||||||
|
}
|
||||||
|
$this->routes = @json_decode($result, true);
|
||||||
|
if ($this->routes === null) {
|
||||||
|
throw new RuntimeException("Failed to parse json output");
|
||||||
|
}
|
||||||
|
foreach ($this->routes as $key => &$route) {
|
||||||
|
if ($route["dst"] === "default") {
|
||||||
|
$route["dst"] = "0.0.0.0/0";
|
||||||
|
} elseif (!str_contains($route["dst"], "/")) {
|
||||||
|
$route["dst"] .= "/32";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!isset($argv[1])) {
|
||||||
|
throw new RuntimeException("Output config is not set");
|
||||||
|
}
|
||||||
|
$config = [];
|
||||||
|
$reader = new RoutingTableReader();
|
||||||
|
$routes = [];
|
||||||
|
$overlapped = [];
|
||||||
|
foreach ($reader->getRoutes() as $route) {
|
||||||
|
if ($route["dst"] == "0.0.0.0/0") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$routes[] = $route;
|
||||||
|
}
|
||||||
|
foreach ($routes as $i => $master) {
|
||||||
|
if (in_array($master, $overlapped)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($routes as $j => $slave) {
|
||||||
|
if ($i == $j or in_array($slave, $overlapped)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_subnet_overlaps($master["dst"], $slave["dst"])) {
|
||||||
|
$overlapped[] = $slave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$subnets = [];
|
||||||
|
foreach ($routes as $i => $master) {
|
||||||
|
if (in_array($master, $overlapped)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$subnets[] = $master["dst"];
|
||||||
|
}
|
||||||
|
foreach ($subnets as $route) {
|
||||||
|
$parts = explode("/", $route);
|
||||||
|
$mask = long2ip(-1 << (32 - (int)$parts[1]));
|
||||||
|
$dst = $parts[0];
|
||||||
|
$config[] = "push \"route {$dst} {$mask}\"";
|
||||||
|
}
|
||||||
|
$outfile = $argv[1];
|
||||||
|
file_put_contents($outfile, implode("\n", $config));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "\nError:" . $e->getMessage() . "\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#keys
|
||||||
|
ca /etc/openvpn/keys/ca.crt
|
||||||
|
cert /etc/openvpn/keys/issued/server.crt
|
||||||
|
key /etc/openvpn/keys/private/server.key
|
||||||
|
dh /etc/openvpn/keys/dh.pem
|
||||||
|
|
||||||
|
#IP settings
|
||||||
|
local 172.16.100.30
|
||||||
|
port 1194
|
||||||
|
proto udp
|
||||||
|
dev tun
|
||||||
|
server 172.16.102.0 255.255.255.128
|
||||||
|
|
||||||
|
#Routing settings
|
||||||
|
push "route 172.16.102.0 255.255.255.0"
|
||||||
|
push "dhcp-option DNS 8.8.8.8"
|
||||||
|
push "dhcp-option DNS 1.1.1.1"
|
||||||
|
|
||||||
|
keepalive 10 120
|
||||||
|
persist-key
|
||||||
|
persist-tun
|
||||||
|
ifconfig-pool-persist ipp.txt
|
||||||
|
status /var/log/openvpn-status.log
|
||||||
|
log-append /var/log/openvpn.log
|
||||||
|
verb 3
|
||||||
|
script-security 2
|
||||||
|
client-connect /etc/openvpn/connect.php
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
# Easy-RSA 3 parameter settings
|
||||||
|
|
||||||
|
# NOTE: If you installed Easy-RSA from your package manager, do not edit
|
||||||
|
# this file in place -- instead, you should copy the entire easy-rsa directory
|
||||||
|
# to another location so future upgrades do not wipe out your changes.
|
||||||
|
|
||||||
|
# HOW TO USE THIS FILE
|
||||||
|
#
|
||||||
|
# vars.example contains built-in examples to Easy-RSA settings. You MUST name
|
||||||
|
# this file "vars" if you want it to be used as a configuration file. If you
|
||||||
|
# do not, it WILL NOT be automatically read when you call easyrsa commands.
|
||||||
|
#
|
||||||
|
# It is not necessary to use this config file unless you wish to change
|
||||||
|
# operational defaults. These defaults should be fine for many uses without
|
||||||
|
# the need to copy and edit the "vars" file.
|
||||||
|
#
|
||||||
|
# All of the editable settings are shown commented and start with the command
|
||||||
|
# "set_var" -- this means any set_var command that is uncommented has been
|
||||||
|
# modified by the user. If you are happy with a default, there is no need to
|
||||||
|
# define the value to its default.
|
||||||
|
|
||||||
|
# NOTES FOR WINDOWS USERS
|
||||||
|
#
|
||||||
|
# Paths for Windows *MUST* use forward slashes, or optionally double-escaped
|
||||||
|
# backslashes (single forward slashes are recommended.) This means your path
|
||||||
|
# to the openssl binary might look like this:
|
||||||
|
# "C:/Program Files/OpenSSL-Win32/bin/openssl.exe"
|
||||||
|
|
||||||
|
# A little housekeeping: DO NOT EDIT THIS SECTION
|
||||||
|
#
|
||||||
|
# Easy-RSA 3.x does not source into the environment directly.
|
||||||
|
# Complain if a user tries to do this:
|
||||||
|
if [ -z "$EASYRSA_CALLER" ]; then
|
||||||
|
echo "You appear to be sourcing an Easy-RSA *vars* file. This is" >&2
|
||||||
|
echo "no longer necessary and is disallowed. See the section called" >&2
|
||||||
|
echo "*How to use this file* near the top comments for more details." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# DO YOUR EDITS BELOW THIS POINT
|
||||||
|
|
||||||
|
# If your OpenSSL command is not in the system PATH, you will need to define
|
||||||
|
# the path here. Normally this means a full path to the executable, otherwise
|
||||||
|
# you could have left it undefined here and the shown default would be used.
|
||||||
|
#
|
||||||
|
# Windows users, remember to use paths with forward-slashes (or escaped
|
||||||
|
# back-slashes.) Windows users should declare the full path to the openssl
|
||||||
|
# binary here if it is not in their system PATH.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_OPENSSL "openssl"
|
||||||
|
#
|
||||||
|
# This sample is in Windows syntax -- edit it for your path if not using PATH:
|
||||||
|
#set_var EASYRSA_OPENSSL "C:/Program Files/OpenSSL-Win32/bin/openssl.exe"
|
||||||
|
|
||||||
|
# Windows users, to generate OpenVPN TLS Keys the Openvpn binary must be
|
||||||
|
# defined here.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_OPENVPN "C:\\Program Files\\Openvpn\\bin\\openvpn.exe"
|
||||||
|
|
||||||
|
# Define X509 DN mode.
|
||||||
|
#
|
||||||
|
# This is used to adjust which elements are included in the Subject field
|
||||||
|
# as the DN ("Distinguished Name"). Note that in 'cn_only' mode the
|
||||||
|
# Organizational fields, listed further below, are not used.
|
||||||
|
#
|
||||||
|
# Choices are:
|
||||||
|
# cn_only - Use just a commonName value.
|
||||||
|
# org - Use the "traditional" format:
|
||||||
|
# Country/Province/City/Org/Org.Unit/email/commonName
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_DN "cn_only"
|
||||||
|
|
||||||
|
# Organizational fields (used with "org" mode and ignored in "cn_only" mode).
|
||||||
|
# These are the default values for fields which will be placed in the
|
||||||
|
# certificate. Do not leave any of these fields blank, although interactively
|
||||||
|
# you may omit any specific field by typing the "." symbol (not valid for
|
||||||
|
# email).
|
||||||
|
#
|
||||||
|
# NOTE: The following characters are not supported
|
||||||
|
# in these "Organizational fields" by Easy-RSA:
|
||||||
|
# back-tick (`)
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_REQ_COUNTRY "US"
|
||||||
|
#set_var EASYRSA_REQ_PROVINCE "California"
|
||||||
|
#set_var EASYRSA_REQ_CITY "San Francisco"
|
||||||
|
#set_var EASYRSA_REQ_ORG "Copyleft Certificate Co"
|
||||||
|
#set_var EASYRSA_REQ_EMAIL "me@example.net"
|
||||||
|
#set_var EASYRSA_REQ_OU "My Organizational Unit"
|
||||||
|
|
||||||
|
# Preserve the Distinguished Name field order
|
||||||
|
# of the certificate signing request
|
||||||
|
# *Only* effective in --dn-mode=org
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_PRESERVE_DN 1
|
||||||
|
|
||||||
|
# Set no password mode - This will create the entire PKI without passwords.
|
||||||
|
# This can be better managed by choosing which entity private keys should be
|
||||||
|
# encrypted with the following command line options:
|
||||||
|
# Global option '--no-pass' or command option 'nopass'.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_NO_PASS 1
|
||||||
|
|
||||||
|
# Choose a size in bits for your keypairs. The recommended value is 2048.
|
||||||
|
# Using 2048-bit keys is considered more than sufficient for many years into
|
||||||
|
# the future. Larger keysizes will slow down TLS negotiation and make key/DH
|
||||||
|
# param generation take much longer. Values up to 4096 should be accepted by
|
||||||
|
# most software. Only used when the crypto alg is rsa, see below.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_KEY_SIZE 2048
|
||||||
|
|
||||||
|
# The default crypto mode is rsa; ec can enable elliptic curve support.
|
||||||
|
# Note that not all software supports ECC, so use care when enabling it.
|
||||||
|
# Choices for crypto alg are: (each in lower-case)
|
||||||
|
# * rsa
|
||||||
|
# * ec
|
||||||
|
# * ed
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_ALGO rsa
|
||||||
|
|
||||||
|
# Define the named curve, used in ec & ed modes:
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_CURVE secp384r1
|
||||||
|
|
||||||
|
# In how many days should the root CA key expire?
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_CA_EXPIRE 3650
|
||||||
|
|
||||||
|
# In how many days should certificates expire?
|
||||||
|
#
|
||||||
|
set_var EASYRSA_CERT_EXPIRE 3650
|
||||||
|
|
||||||
|
# How many days until the Certificate Revokation List will expire.
|
||||||
|
#
|
||||||
|
# IMPORTANT: When the CRL expires, an OpenVPN Server which uses a
|
||||||
|
# CRL will reject ALL new connections, until the CRL is replaced.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_CRL_DAYS 180
|
||||||
|
|
||||||
|
# Random serial numbers by default.
|
||||||
|
# Set to 'no' for the old incremental serial numbers.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_RAND_SN "yes"
|
||||||
|
|
||||||
|
# Cut-off window for checking expiring certificates.
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_PRE_EXPIRY_WINDOW 90
|
||||||
|
|
||||||
|
# Generate automatic subjectAltName for certificates
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_AUTO_SAN 1
|
||||||
|
|
||||||
|
# Add critical attribute to X509 fields: basicConstraints (BC),
|
||||||
|
# keyUsage (KU), extendedKeyUsage (EKU) or SAN
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_BC_CRIT 1
|
||||||
|
#set_var EASYRSA_KU_CRIT 1
|
||||||
|
#set_var EASYRSA_EKU_CRIT 1
|
||||||
|
#set_var EASYRSA_SAN_CRIT 1
|
||||||
|
|
||||||
|
# Disable automatic inline files
|
||||||
|
#
|
||||||
|
#set_var EASYRSA_DISABLE_INLINE 1
|
||||||
|
|
||||||
|
set_var EASYRSA_PKI "/data/pki"
|
||||||
Loading…
Reference in New Issue