Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added auto-setting of www-ssl and api-ssl certificates, extra debugging, support for OpenSSH 7+ #12

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@

*UPD 2018-05-27: Works with wildcard Let's Encrypt Domains*

*UPD 2019-07-11: Works with OpenSSH 7+*

[![Mikrotik](https://i.mt.lv/mtv2/logo.svg)](https://mikrotik.com/)


### How it works:
* Dedicated Linux renew and push certificates to RouterOS / Mikrotik
* After CertBot renew your certificates
* The script connects to RouterOS / Mikrotik using DSA Key (without password or user input)
* The script connects to RouterOS / Mikrotik using RSA Key (without password or user input)
* Delete previous certificate files
* Delete the previous certificate
* Upload two new files: **Certificate** and **Key**
* Import **Certificate** and **Key**
* Change **SSTP Server Settings** to use new certificate
* Delete certificate and key files form RouterOS / Mikrotik storage
* Change **WWW-SSL Service** to use new certificate
* Change **API-SSL Service** to use new certificate
* Delete certificate and key files from RouterOS / Mikrotik storage

### Installation on Ubuntu 16.04
*Similar way you can use on Debian/CentOS/AMI Linux/Arch/Others*
Expand All @@ -35,26 +39,28 @@ vim /opt/letsencrypt-routeros/letsencrypt-routeros.settings
| ROUTEROS_USER | admin | user with admin rights to connect to RouterOS |
| ROUTEROS_HOST | 10.0.254.254 | RouterOS\Mikrotik IP |
| ROUTEROS_SSH_PORT | 22 | RouterOS\Mikrotik PORT |
| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_dsa | Private Key to connecto to RouterOS |
| ROUTEROS_PRIVATE_KEY | /opt/letsencrypt-routeros/id_rsa | Private RSA Key to connect to RouterOS |
| DOMAIN | mydomain.com | Use main domain for wildcard certificate or subdomain for subdomain certificate |
| SETUP_SERVICES | (SSTP WWW API) | Array of services for which certificate will be installed |
| SSH_STRICT_KEY_CHECKING | yes | Allows to override SSH option StrictHostKeyChecking |


Change permissions:
```sh
chmod +x /opt/letsencrypt-routeros/letsencrypt-routeros.sh
```
Generate DSA Key for RouterOS
Generate RSA Key for RouterOS

*Make sure to leave the passphrase blank (-N "")*

```sh
ssh-keygen -t dsa -f /opt/letsencrypt-routeros/id_dsa -N ""
ssh-keygen -t rsa -f /opt/letsencrypt-routeros/id_rsa -N ""
```

Send Generated DSA Key to RouterOS / Mikrotik
Send Generated RSA Key to RouterOS / Mikrotik
```sh
source /opt/letsencrypt-routeros/letsencrypt-routeros.settings
scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_dsa.pub "$ROUTEROS_USER"@"$ROUTEROS_HOST":"id_dsa.pub"
scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_rsa.pub "$ROUTEROS_USER"@"$ROUTEROS_HOST":"id_rsa.pub"
```

### Setup RouterOS / Mikrotik side
Expand All @@ -67,8 +73,8 @@ scp -P $ROUTEROS_SSH_PORT /opt/letsencrypt-routeros/id_dsa.pub "$ROUTEROS_USER"@
:put "Enable SSH"
/ip service enable ssh

:put "Add to the user DSA Public Key"
/user ssh-keys import user=admin public-key-file=id_dsa.pub
:put "Add to the user RSA Public Key"
/user ssh-keys import user=admin public-key-file=id_rsa.pub
```

### CertBot Let's Encrypt
Expand All @@ -92,14 +98,14 @@ certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-
```

### Usage of the script
*To use settings form the settings file:*
*To use settings from the settings file:*
```sh
./opt/letsencrypt-routeros/letsencrypt-routeros.sh
/opt/letsencrypt-routeros/letsencrypt-routeros.sh -c letsencrypt-routeros.settings
```
*To use script without settings file:*

```sh
./opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]
/opt/letsencrypt-routeros/letsencrypt-routeros.sh -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]
```
*To use script with CertBot hooks for wildcard domain:*
```sh
Expand All @@ -110,15 +116,8 @@ certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-publi
certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok --post-hook /opt/letsencrypt-routeros/letsencrypt-routeros.sh
```

### Edit Script
You can easily edit script to execute your commands on RouterOS / Mikrotik after certificates renewal
Add these strings in the «.sh» file before «exit 0» to have www-ssl and api-ssl works with Let's Encrypt SSL
```sh
$routeros /ip service set www-ssl certificate=$DOMAIN.pem_0
$routeros /ip service set api-ssl certificate=$DOMAIN.pem_0
```
---
### Licence MIT
### License MIT
Copyright 2018 Konstantin Gimpel

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Expand Down
7 changes: 6 additions & 1 deletion letsencrypt-routeros.settings
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,10 @@
ROUTEROS_USER=admin
ROUTEROS_HOST=10.0.254.254
ROUTEROS_SSH_PORT=22
ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_dsa
ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_rsa
DOMAIN=vpnserver.yourdomain.com
## Uncomment this to specify array of services that will be setup
## If not specified certificate is installed to (SSTP WWW API)
#SETUP_SERVICES=(WWW API)
## Uncomment this to disable StrictHostKeyChecking (default yes)
#SSH_STRICT_KEY_CHECKING=no
152 changes: 110 additions & 42 deletions letsencrypt-routeros.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,79 +1,147 @@
#!/bin/bash
CONFIG_FILE=letsencrypt-routeros.settings

if [[ -z $1 ]] || [[ -z $2 ]] || [[ -z $3 ]] || [[ -z $4 ]] || [[ -z $5 ]]; then
echo -e "Usage: $0 or $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]\n"
source $CONFIG_FILE
else
ROUTEROS_USER=$1
ROUTEROS_HOST=$2
ROUTEROS_SSH_PORT=$3
ROUTEROS_PRIVATE_KEY=$4
DOMAIN=$5
while getopts 'u:h:p:k:d:f:' OPTION; do
case "$OPTION" in
u)
ROUTEROS_USER=$OPTARG
;;
h)
ROUTEROS_HOST=$OPTARG
;;
p)
ROUTEROS_SSH_PORT=$OPTARG
;;
k)
ROUTEROS_PRIVATE_KEY=$OPTARG
;;
d)
DOMAIN=$OPTARG
;;
f)
CONFIG=$OPTARG
;;
*)
echo "Unknown option '$OPTION'"
;;
esac
done
shift "$((OPTIND - 1))"

if [[ -n $CONFIG ]]; then
source "$CONFIG"
elif [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then
echo -e "Usage:\n$0 -c /path/to/config\nOR\n$0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]"
exit 1
fi

if [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then
echo "Check the config file $CONFIG_FILE or start with params: $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]"
echo "Please avoid spaces"
exit 1
echo "Check the config file $CONFIG_FILE or start with params: $0 -u [RouterOS User] -h [RouterOS Host] -p [SSH Port] -k [SSH Private Key] -d [Domain]"
echo "Please avoid spaces"
exit 1
fi

CERTIFICATE=/etc/letsencrypt/live/$DOMAIN/cert.pem
KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem
CERTIFICATE=/etc/letsencrypt/live/${DOMAIN}/cert.pem
KEY=/etc/letsencrypt/live/${DOMAIN}/privkey.pem

echo ""
echo "Updating certificate for $DOMAIN"
echo " Using certificate $CERTIFICATE"
echo " User private key $KEY"

#Create alias for RouterOS command
routeros="ssh -i $ROUTEROS_PRIVATE_KEY $ROUTEROS_USER@$ROUTEROS_HOST -p $ROUTEROS_SSH_PORT"
routeros="ssh -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -i $ROUTEROS_PRIVATE_KEY ${ROUTEROS_USER}@${ROUTEROS_HOST} -p $ROUTEROS_SSH_PORT"

#Create alias for scp command
scp="scp -q -o PubkeyAcceptedKeyTypes=+ssh-dss -o StrictHostKeyChecking=${SSH_STRICT_KEY_CHECKING:-yes} -P $ROUTEROS_SSH_PORT -i $ROUTEROS_PRIVATE_KEY"

echo ""
echo "Checking connection to RouterOS"

#Check connection to RouterOS
$routeros /system resource print
RESULT=$?

if [[ ! $RESULT == 0 ]]; then
echo -e "\nError in: $routeros"
echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_to_execute_commands_(DSA_key_login)"
exit 1
if [[ ! ${RESULT} == 0 ]]; then
echo -e "\nError in: $routeros"
echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_to_execute_commands_(DSA_key_login)"
exit 1
else
echo -e "\nConnection to RouterOS Successful!\n"
echo -e "\nConnection to RouterOS Successful!\n"
fi

if [ ! -f $CERTIFICATE ] && [ ! -f $KEY ]; then
echo -e "\nFile(s) not found:\n$CERTIFICATE\n$KEY\n"
echo -e "Please use CertBot Let'sEncrypt:"
echo "============================"
echo "certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok"
echo "or (for wildcard certificate):"
echo "certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory"
echo "==========================="
echo -e "and follow instructions from CertBot\n"
exit 1
if [ ! -f "$CERTIFICATE" ] && [ ! -f "$KEY" ]; then
echo -e "\nFile(s) not found:\n${CERTIFICATE}\n${KEY}\n"
echo -e "Please use CertBot Let'sEncrypt:"
echo "============================"
echo "certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok"
echo "or (for wildcard certificate):"
echo "certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory"
echo "==========================="
echo -e "and follow instructions from CertBot\n"
exit 1
fi

# Set up variables to remove errors
DOMAIN_INSTALLED_CERT_FILE=${DOMAIN}.pem_0
DOMAIN_CERT_FILE=${DOMAIN}.pem
DOMAIN_KEY_FILE=${DOMAIN}.key

# Remove previous certificate
$routeros /certificate remove [find name=$DOMAIN.pem_0]
echo "Removing old certificate from installed certificates: $DOMAIN_INSTALLED_CERT_FILE"
$routeros /certificate remove [find name="$DOMAIN_INSTALLED_CERT_FILE"]

echo ""
echo "Handling new certificate file"
# Create Certificate
# Delete Certificate file if the file exist on RouterOS
$routeros /file remove $DOMAIN.pem > /dev/null
echo " Deleting any old copy of certificate file from disk: $DOMAIN_CERT_FILE"
$routeros /file remove "$DOMAIN_CERT_FILE" >/dev/null
# Upload Certificate to RouterOS
scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.pem"
echo " Uploading new domain certificate file to router: $CERTIFICATE"
$scp "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_CERT_FILE"
sleep 2
# Import Certificate file
$routeros /certificate import file-name=$DOMAIN.pem passphrase=\"\"
echo " Importing new certificate file to router certificates"
$routeros /certificate import file-name="$DOMAIN_CERT_FILE" passphrase=\"\"
# Delete Certificate file after import
$routeros /file remove $DOMAIN.pem
echo " Deleting any new copy of certificate file from disk: $DOMAIN_CERT_FILE"
$routeros /file remove "$DOMAIN_CERT_FILE"

echo ""
echo "Handling new key file"
# Create Key
# Delete Certificate file if the file exist on RouterOS
$routeros /file remove $KEY.key > /dev/null
echo " Deleting any old copy of key file from disk: ${DOMAIN_KEY_FILE}"
$routeros /file remove "$DOMAIN_KEY_FILE" >/dev/null
# Upload Key to RouterOS
scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.key"
echo " Uploading new domain key file to router: $KEY"
$scp "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN_KEY_FILE"
sleep 2
# Import Key file
$routeros /certificate import file-name=$DOMAIN.key passphrase=\"\"
echo " Importing new key file to router certificates"
$routeros /certificate import file-name="$DOMAIN_KEY_FILE" passphrase=\"\"
# Delete Certificate file after import
$routeros /file remove $DOMAIN.key
echo " Deleting any new copy of key file from disk: $DOMAIN_KEY_FILE"
$routeros /file remove "$DOMAIN_KEY_FILE"

# Setup Certificate to SSTP Server
$routeros /interface sstp-server server set certificate=$DOMAIN.pem_0
echo ""

# Setup Certificate to SSTP Service
if [[ "${SETUP_SERVICES[*]:-SSTP}" =~ "SSTP" ]]; then
echo "Updating SSTP Server to use $DOMAIN_INSTALLED_CERT_FILE"
$routeros /interface sstp-server server set certificate="$DOMAIN_INSTALLED_CERT_FILE"
fi

# Setup Certificate to WWW Service
if [[ "${SETUP_SERVICES[*]:-WWW}" =~ "WWW" ]]; then
echo "Updating HTTPS Server to use $DOMAIN_INSTALLED_CERT_FILE"
$routeros /ip service set www-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE"
fi

# Setup Certificate to API Service
if [[ "${SETUP_SERVICES[*]:-API}" =~ "API" ]]; then
echo "Updating API SSL Server to use $DOMAIN_INSTALLED_CERT_FILE"
$routeros /ip service set api-ssl certificate="$DOMAIN_INSTALLED_CERT_FILE"
fi

exit 0