{"id":41,"date":"2020-06-21T20:18:46","date_gmt":"2020-06-21T12:18:46","guid":{"rendered":"https:\/\/blog.swineson.me\/en\/?p=41"},"modified":"2020-06-21T20:24:38","modified_gmt":"2020-06-21T12:24:38","slug":"config-openvpn-server-with-routeros-compatibility","status":"publish","type":"post","link":"https:\/\/blog.swineson.me\/en\/config-openvpn-server-with-routeros-compatibility\/","title":{"rendered":"Configure OpenVPN Server with RouterOS compatibility"},"content":{"rendered":"<p>RouterOS has nothing to do with security, so this article will focus on usability rather than security. All configurations related to security will be marked as optional.<\/p>\n<p>First of all, let&#8217;s review all the limitations we have on the OpenVPN client on RouterOS 6.x:<\/p>\n<ul>\n<li>Supported protocol: TCP (TLS mode) only, no UDP, no static key<\/li>\n<li>Supported ciphers: <span class=\"lang:default highlight:0 decode:true crayon-inline\">none BF-CBC AES-128-CBC AES-192-CBC AES-256-CBC<\/span><\/li>\n<li>Supported digest algorithms: <span class=\"lang:default highlight:0 decode:true crayon-inline\">none MD5 SHA1<\/span><\/li>\n<li>Supported authentication methods: username, password and optional client certificate<\/li>\n<li>Does not support MPLS even if running in TAP mode<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<h1>Server Configuration<\/h1>\n<p>We use Debian 10 as an example here.<\/p>\n<h2>Install OpenVPN<\/h2>\n<pre class=\"lang:sh decode:true \">apt-get install -y openvpn<\/pre>\n<h2>Create CA and Server Certificate<\/h2>\n<p>For the sake of simplicity, we directly generate the CA certificate on the same server. This is not safe and is not recommended for production; you should generate the CA private key on an air-gapped computer and generate the server private key and the CSR on the server.<\/p>\n<pre class=\"lang:sh decode:true\">cd \/etc\/openvpn\/server\r\nexport EASYRSA=$(pwd)\r\nexport EASYRSA_EXT_DIR=\/usr\/share\/easy-rsa\/x509-types\r\n\r\n\/usr\/share\/easy-rsa\/easyrsa init-pki\r\ncp \/usr\/share\/easy-rsa\/openssl-easyrsa.cnf \/etc\/openvpn\/server\/pki\/\r\n\r\n\/usr\/share\/easy-rsa\/easyrsa build-ca\r\n# Will prompt for CA private key password, you should remember it\r\n\r\n\/usr\/share\/easy-rsa\/easyrsa gen-req &lt;server-name&gt; nopass\r\n\/usr\/share\/easy-rsa\/easyrsa sign-req server &lt;server-name&gt;\r\n\r\nopenssl dhparam -out dh.pem 2048<\/pre>\n<h2>Create Server Configuration<\/h2>\n<pre class=\"lang:default decode:true\">dev ovpn-server1\r\nport 1194\r\n# Client IP pool\r\nserver 192.168.1.0 255.255.255.0\r\n\r\n# connection properties\r\ndev-type tap\r\nproto tcp4-server\r\n#comp-lzo\r\nkeepalive 10 60\r\nping-timer-rem\r\npersist-tun\r\npersist-key\r\n\r\n# security setup\r\ncipher AES-256-CBC\r\nscript-security 2\r\nuser nobody\r\ngroup nogroup\r\n\r\n# MTU setup\r\nmtu-disc yes\r\n#link-mtu 1492\r\n#mtu-test\r\n#tun-mtu 1464\r\n#mssfix\r\n\r\n# server cert setup\r\nca pki\/ca.crt\r\ncert pki\/issued\/&lt;server-name&gt;.crt\r\nkey pki\/private\/&lt;server-name&gt;.key\r\ndh dh.pem\r\n\r\n# if you don't need client cert \r\nusername-as-common-name\r\nverify-client-cert none\r\n\r\n# username password auth script\r\nauth-nocache\r\nauth-user-pass-verify user-pass-auth.sh via-file\r\n\r\n# If you need to put the interface into a VRF\r\n#up \"up-vrf.sh vrf1\"<\/pre>\n<h2>Create Username Password Authentication Script<\/h2>\n<p>OpenVPN does not support username\/password database natively. Either you need to configure PAM (which means you need a corresponding Linux user for every VPN user or mess up with PAM configuration), or you write your own program to deal with username and password on each login. We&#8217;ll use the latter. When the program is invoked, it have a filename as an argument; the first line of the file will be the username and the second line will be the password. If the program returns 0 then it is a successful login. Let&#8217;s just quickly write a bash script and hardcode everything:<\/p>\n<pre class=\"lang:sh decode:true\">#!\/bin\/bash\r\n# Simple OpenVPN user-pass-auth program\r\nset -Eeuo pipefail\r\n\r\nreadarray -t line &lt; $1\r\n\r\nif [ \"${line[0]}\" == \"username\" ] &amp;&amp; [  \"${line[1]}\" == \"password\" ]; then\r\n        exit 0\r\nelse\r\n        exit 1\r\nfi<\/pre>\n<p>Save this file as <span class=\"lang:default highlight:0 decode:true crayon-inline \">user-pass-auth.sh<\/span> and give it execute permission.<\/p>\n<h2>(Optional) Add Interface to VRF<\/h2>\n<pre class=\"lang:sh decode:true\">#!\/bin\/bash\r\nset -Eeuo pipefail\r\n\r\n# User-provided arguments\r\nVRF=$1\r\n\r\n# Default arguments\r\nDEV=$2\r\nTUN_MTU=$3\r\nLINK_MTU=$4\r\nIFCONFIG_LOCAL_IP=$5\r\nIFCONFIG_REMOTE_IP=$6\r\nOPERATION=$7\r\n\r\n#echo \"Device: $DEV\"\r\n#echo \"Args: $@\"\r\n\r\nip link set $DEV up\r\nip link set $DEV vrf $VRF<\/pre>\n<h1>Client Config on RouterOS<\/h1>\n<h2>(Optional) Create Client Certificate<\/h2>\n<ol>\n<li>Generate private key and CSR on the client<\/li>\n<li>Copy the CSR to the CA server<\/li>\n<li>CA server signs the CSR to generate the certificate<\/li>\n<li>Import the certificate back to the client<\/li>\n<\/ol>\n<h2>(Optional) Import CA<\/h2>\n<ol>\n<li>Import the CA on the client<\/li>\n<\/ol>\n<h2>Create the Interface<\/h2>\n<pre class=\"lang:default decode:true \">\/interface ovpn-client\r\nadd name=ovpn-out-test connect-to=&lt;server-ip-or-fqdn&gt; port=1194 mode=ethernet user=username password=password cipher=aes256<\/pre>\n<p>If you&#8217;ve imported the CA (recommended), then tick &#8220;Verify Server Certificate&#8221;. If you created a client certificate, choose it in the &#8220;Certificate&#8221; dropdown.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>RouterOS has nothing to do with security, so this article will focus on usability rather than security. All configurations related to security will be marked as optional. First of all, let&#8217;s review all the limitations we have on the OpenVPN client on RouterOS 6.x: Supported protocol: TCP (TLS mode) only, no UDP, no static key [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2,5,6],"tags":[],"class_list":["post-41","post","type-post","status-publish","format-standard","hentry","category-linux","category-networking","category-routeros"],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/41"}],"collection":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/comments?post=41"}],"version-history":[{"count":2,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/41\/revisions"}],"predecessor-version":[{"id":43,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/41\/revisions\/43"}],"wp:attachment":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/media?parent=41"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/categories?post=41"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/tags?post=41"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}