Quantum Computation and Information Security (David Webber)

Secure communication on the internet relies on asymmetric (public-private) key pairs to encrypt and/or sign digital messages. The security of public-private key algorithms is based on the belief that factoring large numbers is computationally difficult and practically impossible. On classical computers running state-of-the art algorithms this is true. However, a new class of so-called “quantum computers” currently under development by researchers around the world will be able to short-cut this factoring problem. In this talk I’ll give an overview of how quantum computers will be able to break RSA encryption (and hence existing internet security), and describe another way to securely transmit digital messages that, based on the fundamental laws of physics, is provably unbreakable. This talk will be light on math with plenty of analogies and entertaining thought experiments.

Using TLS1.3 With OpenSSL

The forthcoming OpenSSL 1.1.1 release will include support for TLSv1.3. The new
release will be binary and API compatible with OpenSSL 1.1.0. In theory, if your
application supports OpenSSL 1.1.0, then all you need to do to upgrade is to drop
in the new version of OpenSSL when it becomes available and you will
automatically start being able to use TLSv1.3. However there are some issues
that application developers and deployers need to be aware of. In this blog post
I am going to cover some of those things.

Differences with TLS1.2 and below

TLSv1.3 is a major rewrite of the specification. There was some debate as to
whether it should really be called TLSv2.0 – but TLSv1.3 it is. There are major
changes and some things work very differently. A brief, incomplete, summary of
some things that you are likely to notice follows:

  • There are new ciphersuites that only work in TLSv1.3. The old ciphersuites
    cannot be used for TLSv1.3 connections.
  • The new ciphersuites are defined differently and do not specify the
    certificate type (e.g. RSA, DSA, ECDSA) or the key exchange mechanism (e.g.
    DHE or ECHDE). This has implications for ciphersuite configuration.
  • Clients provide a “key_share” in the ClientHello. This has consequences for
    “group” configuration.
  • Sessions are not established until after the main handshake has been
    completed. There may be a gap between the end of the handshake and the
    establishment of a session (or, in theory, a session may not be established at
    all). This could have impacts on session resumption code.
  • Renegotiation is not possible in a TLSv1.3 connection
  • More of the handshake is now encrypted.
  • More types of messages can now have extensions (this has an impact on the
    custom extension APIs and Certificate Transparency)
  • DSA certificates are no longer allowed in TLSv1.3 connections

Note that at this stage only TLSv1.3 is supported. DTLSv1.3 is still in the
early days of specification and there is no OpenSSL support for it at this time.

Current status of the TLSv1.3 standard

As of the time of writing TLSv1.3 is still in draft. Periodically a new version
of the draft standard is published by the TLS Working Group. Implementations of
the draft are required to identify the specific draft version that they are
using. This means that implementations based on different draft versions do not
interoperate with each other.

OpenSSL 1.1.1 will not be released until (at least) TLSv1.3 is finalised. In the
meantime the OpenSSL git master branch contains our development TLSv1.3 code
which can be used for testing purposes (i.e. it is not for production use). You
can check which draft TLSv1.3 version is implemented in any particular OpenSSL
checkout by examining the value of the TLS1_3_VERSION_DRAFT_TXT macro in the
tls1.h header file. This macro will be removed when the final version of the
standard is released.

In order to compile OpenSSL with TLSv1.3 support you must use the
“enable-tls1_3” option to “config” or “Configure”.

Currently OpenSSL has implemented the “draft-20” version of TLSv1.3. Many other
libraries are still using older draft versions in their implementations. Notably
many popular browsers are using “draft-18”. This is a common source of
interoperability problems. Interoperability of the draft-18 version has been
tested with BoringSSL, NSS and picotls.

Within the OpenSSL git source code repository there are two branches:
“tls1.3-draft-18” and “tls1.3-draft-19”, which implement the older TLSv1.3 draft
versions. In order to test interoperability with other TLSv1.3 implementations
you may need to use one of those branches. Note that those branches are
considered temporary and are likely to be removed in the future when they are no
longer needed.


OpenSSL has implemented support for five TLSv1.3 ciphersuites as follows:

  • TLS13-AES-256-GCM-SHA384
  • TLS13-CHACHA20-POLY1305-SHA256
  • TLS13-AES-128-GCM-SHA256
  • TLS13-AES-128-CCM-8-SHA256
  • TLS13-AES-128-CCM-SHA256

Of these the first three are in the DEFAULT ciphersuite group. This means that
if you have no explicit ciphersuite configuration then you will automatically
use those three and will be able to negotiate TLSv1.3.

All the TLSv1.3 ciphersuites also appear in the HIGH ciphersuite alias. The
ciphersuite aliases include a subset of these ciphersuites as you would expect
based on their names. Key exchange and authentication properties were part of
the ciphersuite definition in TLSv1.2 and below. This is no longer the case in
TLSv1.3 so ciphersuite aliases such as ECDHE, ECDSA, RSA and other similar
aliases do not contain any TLSv1.3 ciphersuites.

If you explicitly configure your ciphersuites then care should be taken to
ensure that you are not inadvertently excluding all TLSv1.3 compatible
ciphersuites. If a client has TLSv1.3 enabled but no TLSv1.3 ciphersuites
configured then it will immediately fail (even if the server does not support
TLSv1.3) with an error message like this:

140460646909376:error:141A90B5:SSL routines:ssl_cipher_list_to_bytes:no ciphers available:ssl/statem/statem_clnt.c:3562:No ciphers enabled for max supported SSL/TLS version

Similarly if a server has TLSv1.3 enabled but no TLSv1.3 ciphersuites it will
also immediately fail, even if the client does not support TLSv1.3, with an
error message like this:

140547390854592:error:141FC0B5:SSL routines:tls_setup_handshake:no ciphers available:ssl/statem/statem_lib.c:108:No ciphers enabled for max supported SSL/TLS version

For example, setting a ciphersuite selection string of
ECDHE:!COMPLEMENTOFDEFAULT will work in OpenSSL 1.1.0 and will only select
those ciphersuites that are in DEFAULT and also use ECDHE for key exchange.
However no TLSv1.3 ciphersuites are in the ECDHE group so this ciphersuite
configuration will fail in OpenSSL 1.1.1 if TLSv1.3 is enabled.

You may want to explicitly list the TLSv1.3 ciphersuites you want to use to
avoid problems. For example:


You can test which ciphersuites are included in a given ciphersuite selection
string using the openssl ciphers -s -v command:

$ openssl ciphers -s -v "ECDHE:!COMPLEMENTOFDEFAULT"

Ensure that at least one ciphersuite supports TLSv1.3


In TLSv1.3 the client selects a “group” that it will use for key exchange.
At the time of writing, OpenSSL only supports ECDHE groups for this (it is
possible that DHE groups will also be supported by the time OpenSSL 1.1.1 is
actually released). The client then sends “key_share” information to the server
for its selected group in the ClientHello.

The list of supported groups is configurable. It is possible for a client to
select a group that the server does not support. In this case the server
requests that the client sends a new key_share that it does support. While this
means a connection will still be established (assuming a mutually supported
group exists), it does introduce an extra server round trip – so this has
implications for performance. In the ideal scenario the client will select a
group that the server supports in the first instance.

In practice most clients will use X25519 or P-256 for their initial key_share.
For maximum performance it is recommended that servers are configured to support
at least those two groups and clients use one of those two for its initial
key_share. This is the default case (OpenSSL clients will use X25519).

The group configuration also controls the allowed groups in TLSv1.2 and below.
If applications have previously configured their groups in OpenSSL 1.1.0 then
you should review that configuration to ensure that it still makes sense for
TLSv1.3. The first named (i.e. most preferred group) will be the one used by an
OpenSSL client in its intial key_share.

Applications can configure the group list by using SSL_CTX_set1_groups() or a
similar function (see
here for
further details). Alternatively, if applications use SSL_CONF style
configuration files then this can be configured using the Groups or Curves
command (see


In TLSv1.2 and below a session is established as part of the handshake. This
session can then be used in a subsequent connection to achieve an abbreviated
handshake. Applications might typically obtain a handle on the session after a
handshake has completed using the SSL_get1_session() function (or similar). See
here for
further details.

In TLSv1.3 sessions are not established until after the main handshake has
completed. The server sends a separate post-handshake message to the client
containing the session details. Typically this will happen soon after the
handshake has completed, but it could be sometime later (or not at all).

The specification recommends that applications only use a session once (although
this is not enforced). For this reason some servers send multiple session
messages to a client. To enforce the “use once” recommendation applications could
use SSL_CTX_remove_session() to mark a session as non-resumable (and remove it
from the cache) once it has been used.

The old SSL_get1_session() and similar APIs may not operate as expected for
client applications written for TLSv1.2 and below. Specifically if a client
application calls SSL_get1_session() before the server message containing
session details has been received then an SSL_SESSION object will still be
returned, but any attempt to resume with it will not succeed and a full
handshake will occur instead. In the case where multiple sessions have been sent
by the server then only the last session will be returned by

Client application developers should consider using the
SSL_CTX_sess_set_new_cb() API instead (see
This provides a callback mechanism which gets invoked every time a new session
is established. This can get invoked multiple times for a single connection if a
server sends multiple session messages.

Note that SSL_CTX_sess_set_new_cb() was also available in OpenSSL 1.1.0.
Applications that already used that API will still work, but they may find that
the callback is invoked at unexpected times, i.e. post-handshake.

An OpenSSL server will immediately attempt to send session details to a client
after the main handshake has completed. To server applications this
post-handshake stage will appear to be part of the main handshake, so calls to
SSL_get1_session() should continue to work as before.

Custom Extensions and Certificate Transparency

In TLSv1.2 and below the initial ClientHello and ServerHello messages can
contain “extensions”. This allows the base specifications to be extended with
additional features and capabilities that may not be applicable in all scenarios
or could not be foreseen at the time that the base specifications were written.
OpenSSL provides support for a number of “built-in” extensions.

Additionally the custom extensions API provides some basic capabilities for
application developers to add support for new extensions that are not built-in
to OpenSSL.

Built on top of the custom extensions API is the “serverinfo” API. This provides
an even more basic interface that can be configured at run time. One use case
for this is Certificate Transparency. OpenSSL provides built-in support for the
client side of Certificate Transparency but there is no built-in server side
support. However this can easily be achieved using “serverinfo” files. A
serverinfo file containing the Certificate Transparency information can be
configured within OpenSSL and it will then be sent back to the client as

In TLSv1.3 the use of extensions is expanded significantly and there are many
more messages that can include them. Additionally some extensions that were
applicable to TLSv1.2 and below are no longer applicable in TLSv1.3 and some
extensions are moved from the ServerHello message to the EncryptedExtensions
message. The old custom extensions API does not have the ability to specify
which messages the extensions should be associated with. For that reason a new
custom extensions API was required.

The old API will still work, but the custom extensions will only be added where
TLSv1.2 or below is negotiated. To add custom extensions that work for all TLS
versions application developers will need to update their applications to the
new API (see
for details).

The “serverinfo” data format has also been updated to include additional
information about which messages the extensions are relevant to. Applications
using “serverinfo” files may need to update to the “version 2” file format to be
able to operate in TLSv1.3 (see
and here
for details).


TLSv1.3 does not have renegotiation so calls to SSL_renegotiate() or
SSL_renegotiate_abbreviated() will immediately fail if invoked on a connection
that has negotiated TLSv1.3.

The most common use case for renegotiation is to update the connection keys. The
function SSL_key_update() can be used for this purpose in TLSv1.3 (see

DSA certificates

DSA certificates are no longer allowed in TLSv1.3. If your server application is
using a DSA certificate then TLSv1.3 connections will fail with an error message
similar to the following:

140348850206144:error:14201076:SSL routines:tls_choose_sigalg:no suitable signature algorithm:ssl/t1_lib.c:2308:

Please use an ECDSA or RSA certificate instead.


TLSv1.3 represents a significant step forward and has some exciting new features
but there are some hazards for the unwary when upgrading. Mostly these issues
have relatively straight forward solutions. Application developers should review
their code and consider whether anything should be updated in order to work more
effectively with TLSv1.3. Similarly application deployers should review their

CCS Injection Vulnerability


OpenSSL’s ChangeCipherSpec processing has a serious vulnerability.
This vulnerability allows malicious intermediate nodes to intercept
encrypted data and decrypt them while forcing SSL clients to use weak
keys which are exposed to the malicious nodes. Because both of servers
and clients are affected by this vulnerabitlity, every OpenSSL user
should update their software immediately. This vulnerabitlity has
enough reproducibility and it is very likely for attackers to utilize
this vulnerabitlity for target attacks.


You can apply software updates from each software vendors.
Refer to the URLs below.


We discovered that OpenSSL’s flaw with ChangeCipherSpec processings
make it possible for malicious third parties to intermediate specific
communication. Through this bug, attackers are able to enforce OpenSSL
servers and clients to use weak key materials. There are risks of
tampering with and exploits on contents and authentication information
over encrypted communication via web browsing, E-mail and VPN, when
the software uses the affected version of OpenSSL.

Q. How does the vulnerability work?

Attackers can predict temporal encryption key materials of any
communication by sending invalid signals in the handshake sessions.
If attackers grasp the key materials, they can eavesdrop the encrypted
communication or steal your identity.

Q. What versions of OpenSSL are affected?

A. Affected Versions:

  • OpenSSL 1.0.1 through 1.0.1g
  • OpenSSL 1.0.0 through 1.0.0l
  • all versions before OpenSSL 0.9.8y

Not Affected Versions:

  • OpenSSL 1.0.1h
  • OpenSSL 1.0.0m
  • OpenSSL 0.9.8za

The latest OpenSSL update includes seven bug fixes. We found one of the

Q. What are the risks?

A. Attackers can eavesdrop and make falsifications on your communication
when both of a server and a client are vulnerable,
and the OpenSSL version of the server is 1.0.1 or higher.

Attackers can hijack the authenticated session,
if the server is vulnerable (even if the client is not vulnerable).

(According to the analysys from Adam Langley and IIJ, If users are
using client certificates, the sessions to the servers will be
disconnected just after attackers attempt to hijack.)

Victims cannot find any trace of the attacks. If you assume the
communication is safe and send password or credit card numbers via
encrypted sessions, you are at the risk of identity theft. In the case
attackers make the falsification on the contents of communication,
attackers may use your identify information to remit money from your
account illegally.

Q. How can I prevent the attacks?

A. If you use Android or Linux, apply the vendor updates because
Android and Linux uses OpenSSL. If you are using Windows, Mac or
iPhone, there are no risks regarding to this vulnerability.

Through this bug, attackers pretend to be intermediate nodes between
victims and servers, and eavesdrop and make falsifications on your
communication. This kind of attacks are called “Man in the
Middle(MITM)” attacks. Under the public WiFi networks, it is very
likely to be attacked through MITM. When you use Internet banking or
Electronic commerce systems, you should avoid connecting to public
WiFi networks and connect your device to cellular networks such as 3G
or LTE networks.

Q. Do I have to re-create my private keys or certificates?

A. No. Attackers cannot steal your private keys through this bug itself.
However if you have transferred your private keys via paths protected by SSL/TLS,
the keys could be sniffed.
If this is the case, consider regenerating the keys or certificates.

Q. Is CCS injection because of an SSL/TLS specification defect?

A. No. It is OpenSSL implementation problem.

Q. What protocol versions are affected?

A. All versions (SSL3.0, TLS1.0, TLS1.1, TLS1.2) are affected.

Q. What encryption algorithms are affected?

A. All encryption algorithms are affected.

Q. Can I detect if someone has exploited this against me?

A. Exploitation of this bug do not leave any traces.

Q. Can IDS/IPS detect this attack?

A. Configuring your IDS/IPS to detect invalid order of messages enables your IDS/IPS to detect the attacks.

Q. How did you find this bug?

A. This bug was discovered by Masashi Kikuchi of Lepidum.
He found this bug while studying safe TLS implementations using a proof assistant system Coq.

Q. How do you report this vulnerability?

A. After we found the vulnerability, we reported it to JPCERT and
CERT/CC. Then JPCERT announced a security alert to the related
partners through the vulnerability handling system. JPCERT and CERT/CC
notified the bug to the OpenSSL developers. Based on the contacts from
the OpenSSL developer team, we supported to develop the bug fix patch.


You can use CCS Injection logo under the terms of CC0. download logo in SVG format

Change History

  • Updated: (Mon, 09 Jun 2014 12:00:00 +0900):
    • Added examples of the risks.
    • Authentication hijack scenario was denied.
  • First Virsion: (Thu, 06 Jun 2014 20:44:00 +0900)

Frozenstar has a CAA dns record

Posted by in SSL Labs
Certification Authority Authorization (CAA), specified in RFC 6844 in 2013, is a proposal to improve the strength of the PKI ecosystem with a new control to restrict which CAs can issue certificates for a particular domain name.

   The Certification Authority Authorization (CAA) DNS Resource Record
   allows a DNS domain name holder to specify one or more Certification
   Authorities (CAs) authorized to issue certificates for that domain.
   CAA Resource Records allow a public Certification Authority to
   implement additional controls to reduce the risk of unintended
   certificate mis-issue.  This document defines the syntax of the CAA
   record and rules for processing CAA records by certificate issuers.

Although CAA had been in the proposed-standard state for more than 4 years, there was little obvious happening until very recently, with only a hundred or two hundred sites adopting it. But that’s going to change, because the CA/Browser Forum recently voted to mandate CAA support as part of its certificate issuance standard Baseline Requirements. The changes will become effective in September 2017.

The fact that any CA can issue a certificate for any domain name is commonly cited as the weakest aspect of the PKI ecosystem. Although CAs want to do the right thing, there are no technical controls that prevent them from doing whatever they chose to do. That’s why we say that the PKI ecosystem is a weak as the weakest link. With hundreds of CAs, there are potentially many weak links.

CAA creates a DNS mechanism that enables domain name owners to whitelist CAs that are allowed to issue certificates for their hostnames. It operates via a new DNS resource record (RR) called CAA (type 257). Owners can restrict certificate issuance by specifying zero or more CAs; if a CA is allowed to issue a certificate, their own hostname will be in the DNS record. For example, this is what someone’s CAA configuration could be (in the zone file): has CAA record 0 issue ""

And that’s all there is to it. Before issuing a certificate, CAs are expected to check the DNS record and refuse issuance unless they find themselves on the whitelist. In addition to the “issue” directive from the example, two other directives are supported: “issuewild” that restricts issuance of wildcard certificates, and “iodef”, which provides support for notification in the cases something goes wrong. (In case you’re wondering, the number “128” is a flags byte with its highest bit set, meaning the directive use is considered critical and must be followed.)

At a high level, CAA has similar purpose to public key pinning (HPKP), but the implementation is entirely different. First, CAA prevents certificate issuance whereas HPKP is a run-time client-side control that prevents already-issued certificates from being seen as valid. In other words, CAA is for CAs, HPKP is for browsers. HPKP, which works by whitelisting public keys, is a strong technical control; in contrast CAA is largely an administrative control. While it’s expected that CAs will automatically check CAA before issuing certificates, what happens next is somewhat vague—they switch to manual processing and may end up issuing the certificate if they believe that the request is genuine. The main weakness of CAA compared to HPKP is that there are many CAs and that they all need to implement the checks correctly, as well as resist social engineering attacks when CAA is violated.

But this is not to say that CAA is useless, or inferior to HPKP. That’s because of the advantages, the main being that, unlike HPKP, which is potentially very dangerous, it’s not possible to abuse CAA and bring down a web property. Whereas HPKP can kill your business if you mess up, CAA will merely annoy you. In the end, one way to look at CAA is “public key pinning for normal web properties”, who would find HPKP to complicated and scary to use.

In case you’re wondering, SSL Labs already supports checking for CAA. You can see it in the report for, for example. (It’s in the top section, along with the information on the key and first certificate.)

Frozenstar VPN

Frozenstar VPN

Frozenstar VPN is based on OpenVPN. it’s fast, secure ,it has support for authentication SHA512, encrypts data channel packets with cipher algorithm AES-256-GCM, it has an additional layer of HMAC authentication on top of the TLS control channel to mitigate DoS attacks .

The secure socket protocol is restricted to Tlsv1.2 ciphers and certificates have a key size of 4096 bits .


All of these are DHE or ECDHE enabled ciphersuites which means key exchange is done with Diffie-Hellman enabled, providing forward secrecy. ECDHE is preferred, because it is faster by the use of elliptic curve cryptography rather than the much slower plain Diffie-Hellman.

You can mail me and request an account (gpg encrypted only) and i will send you all needed configurations, instructions and SSL certificates necessary to connect with your vpn client application. You can download my Gnupg key from here: 0x81D613172B64106C

Key fingerprint = 689C 7073 C1A9 57EF 857C  3341 81D6 1317 2B64 106C


Publish Gnupg Keys in DNS

Publishing PGP Keys in the DNS

Written 6 years ago by Mike Cardwell

I found out today that it’s possible to publish your public PGP key in the DNS. There is a really good guide at which explains the three different methods in detail. It’s really simple though, so I’ll explain how I did it. I’m going to replace my email address with a fake address to avoid feeding the spambots.

First of all, you need to export your public key and place it somewhere where it can be served via HTTP:

gpg -a --export > /var/www/

In this example, that places the key up at Next, you need to find out your public keys fingerprint (highlighted):

mike@server:~$ gpg --fingerprint --list-keys
pub   4096R/0018461F 2010-11-02 [expires: 2015-11-01]
      Key fingerprint = *35BC AF1D 3AA2 1F84 3DC3  B0CF 70A5 F512 0018 461F*
uid                  Mike Cardwell (Personal mail) <>
sub   4096R/01DE408F 2010-11-02 [expires: 2015-11-01]


Then you simply create a DNS TXT record. The hostname is “” ie, “local_part._pka.domain“ and the value looks like this:


“fpr” is the upper-case value of the keys fingerprint without the spaces, and “uri” is the location of the public key.

So what’s the point of this? This command will automatically fetch the public key of and start encrypting with it:

gpg --auto-key-locate pka -ea -r

If you put “auto-key-locate pka” in your gpg.conf you don’t even need to specify it on the command line. It will automatically look up missing keys in the DNS when it needs to. No need for keyservers.

Xmpp chat at

The server allows in-band registration so you can create an account from within a standard client such as Pidgin or Adium or ChatSecure on Android or Apple iOS.

If you have any complaints about abusive behavior from any accounts on the server please email info(AT) with full details

Data retention policies

The server does not create any records of who you communicate with.

It does not log the content of any communications ( and in fact since the server forces you to use Off-The-Record Messaging, we can never get access to the plain text of your communications ) For more information about what Off-The-Record is and why we require it, as well as links to XMPP clients that support OTR, see this page.

If you choose to access the server via its Tor hidden service then we know virtually nothing about you. We can’t know what ISP you use, or even what country you live in.

The use of this server is governed by our privacy policy.

A few notes about the security of the server ( and its associated records)

Our intention is to take security on this server to the highest possible level we can achieve. In pursuit of that goal, we have taken the following precautions:

StartTLS / SSL encryption is required for all client connections. The server is configured to prefer ephemeral ( Forward Secrecy ) encryption ciphers, but will fall back to AES256-SHA or AES128-GCM-SHA256 if servers or clients don’t support the ephemeral flavors.

Our RSA key size is 4096 bits. In recent years, various security organizations have recommended that RSA key sizes less than 2048 bits be discontinued. In particular the United States National Institute of Standards and Technology (NIST) recommends using 2048 bit RSA keys until 2030 at which time it predicts they will not be considered strong enough any longer. But really, why wait until 2030 ? We have chosen to skip 2048 bits and have adopted a 4096 bit key size now.

Tor Hidden Service – So that users can access the server more anonymously, it is also available as a Tor hidden service at the address: potu7aaoitlajnxc.onion If you use XMPP through the .onion address then that makes it much more difficult for observers to know ( through metadata collection or passive observation ) who is connecting to the server. At the moment the only client that we know of that has built-in ability is ChatSecure on Android. It should be possible with just about any client however to direct it to use a tor socks proxy.

The server now forces the use of Off The Record Messaging to further encrypt your private conversations end-to-end. We invite you to read this guide using OTR on Mac OS X with Adium. We intend to write similar documents for Windows / Pidgin and other combinations. If you would like to help with this type of writing then please get in touch.

If you use OTR + SSL + Tor then you will have taken perhaps the most conservative steps presently available to the general public to ensure the security of your instant messaging.

Using Ed25519 for OpenSSH keys (instead of DSA/RSA/ECDSA)

Author: Michael Boelen

Introduction into Ed25519

OpenSSH 6.5 added support for Ed25519 as a public key type. It is using an elliptic curve signature scheme, which offers better security than ECDSA and DSA. At the same time it also has good performance. This type of keys may be used for user and host keys. With this in mind, it is great to be used together with OpenSSH. In this article we have a look at this new key type.


Many forum threads have been created regarding the choice between DSA or RSA. DSA is being limited to 1024 bits, as specified by FIPS 186-2. This is also the default length of ssh-keygen. While the length can be increased, it may not be compatible with all clients. So it is common to see RSA keys, which are often also used for signing. With Ed25519 now available, the usage for both will slowly decrease.

Configuring the server

The first thing to check is if your current OpenSSH package is up-to-date. You will need at least version 5.6 of OpenSSH.

Create SSH host keys

[root@arch ~]# cd /etc/ssh
[root@arch ssh]# mkdir backup
[root@arch ssh]# mv ssh_host_* ./backup/
[root@arch ssh]# ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519
Generating public/private ed25519 key pair.
Your identification has been saved in etc/ssh/ssh_host_ed25519_key.
Your public key has been saved in etc/ssh/
The key fingerprint is:
96:67:0f:50:8d:16:51:c2:47:9c:4e:85:b4:79:bd:6b root@arch
The key's randomart image is:
+--[ED25519 256]--+
|         .=X++.  |
|         .+.Bo . |
|        .. +o . .|
|         o  ..  .|
|        S +    . |
|       . o o    .|
|            .  E |
|              .  |
|                 |

Change SSH configuration (server)

Next step is changing the sshd_config file. Add the new host key type:

HostKey /etc/ssh/ssh_host_ed25519_key

Remove any of the other HostKey settings that are defined.

Client Configuration

After configuring the server, it is time to do the client. We have to create a new key first. Make sure that your ssh-keygen is also up-to-date, to support the new key type. Note: the tilde (~) is an alias for your home directory and expanded by your shell.

$ ssh-keygen -t ed25519 -C ""
 Generating public/private ed25519 key pair.
 Enter file in which to save the key (/home/michael/.ssh/id_ed25519):
 Enter passphrase (empty for no passphrase):
 Enter same passphrase again:
 Your identification has been saved in /home/michael/.ssh/id_ed25519.
 Your public key has been saved in /home/michael/.ssh/
 The key fingerprint is:
 The key's randomart image is:
 +--[ED25519 256]--+
 |                 |
 |          .      |
 |    . .  . .     |
 |   . o .  o o    |
 |    o . S= . + . |
 |   . o  o + o o .|
 |  . . .. o o .  .|
 |   . .  E o     .|
 |      ..   ....o.|

Optional step: Check the key before copying it.

ssh-keygen -l -f ~/.ssh/

If that looks good, copy it to the destination host.

ssh-copy-id -i ~/.ssh/ michael@

Then determine if we can log in with it.

$ ssh -i ~/.ssh/id_ed25519 michael@ Enter passphrase for key ‘~/.ssh/id_ed25519’:

When using this newer type of key, you can configure to use it in your local SSH configuration file (~/.ssh/config). Defining the key file is done with the IdentityFile option.

Host [name]
HostName [hostname]
User [your-username]
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes

Insight: using -o

Normally you can use the -o option to save SSH private keys using the new OpenSSH format. It uses bcrypt/pbkdf2 to hash the private key, which makes it more resilient against brute-force attempts to crack the password. Only newer versions (OpenSSH 6.5+) support it though. For this key type, the -o option is implied and does not have to be provided. Also a bit size is not needed, as it is always 256 bits for this key type.

Secure Secure SHELL


You may have heard that the NSA can decrypt SSH at least some of the time.
If you have not, then read the latest batch of Snowden documents now.
All of it.
This post will still be here when you finish.
My goal with this post here is to make NSA analysts sad.

TL;DR: Scan this post for fixed width fonts, these will be the config file snippets and commands you have to use.

Warning: You will need a recent OpenSSH version.
It should work with 6.5 but I have only tested 6.7 and connections to Github.
Here is a good compatibility matrix.

The crypto

Reading the documents, I have the feeling that the NSA can 1) decrypt weak crypto and 2) steal keys.
Let’s focus on the crypto first.
SSH supports different key exchange algorithms, ciphers and message authentication codes.
The server and the client choose a set of algorithms supported by both, then proceed with the key exchange.
Some of the supported algorithms are not so great and should be disabled completely.
This hurts interoperability but everyone uses OpenSSH anyway.
Fortunately, downgrade attacks are not possible because the supported algorithm lists are included in the key derivation.
If a man in the middle were to change the lists, then the server and the client would calculate different keys.

Key exchange

There are basically two ways to do key exchange: Diffie-Hellman and Elliptic Curve Diffie-Hellman.
Both provide forward secrecy which the NSA hates because they can’t use passive collection and key recovery later.
The server and the client will end up with a shared secret number at the end without a passive eavesdropper learning anything about this number.
After we have a shared secret we have to derive a cryptographic key from this using a key derivation function.
In case of SSH, this is a hash function.
Collision attacks on this hash function have been proven to allow downgrade attacks.

DH works with a multiplicative group of integers modulo a prime.
Its security is based on the hardness of the discrete logarithm problem.

Alice           Bob
Sa = random
Pa = g^Sa   --> Pa
                Sb = random
Pb          <-- Pb = g^Sb
s = Pb^Sa       s = Pa^Sb
k = KDF(s)      k = KDF(s)

ECDH works with elliptic curves over finite fields.
Its security is based on the hardness of the elliptic curve discrete logarithm problem.

Alice           Bob
Sa = random
Pa = Sa * G --> Pa
                Sb = random
Pb          <-- Pb = Sb * G
s = Sa * Pb     s = Sb * Pa
k = KDF(s)      k = KDF(s)

OpenSSH supports 8 key exchange protocols:

  1. curve25519-sha256: ECDH over Curve25519 with SHA2
  2. diffie-hellman-group1-sha1: 1024 bit DH with SHA1
  3. diffie-hellman-group14-sha1: 2048 bit DH with SHA1
  4. diffie-hellman-group-exchange-sha1: Custom DH with SHA1
  5. diffie-hellman-group-exchange-sha256: Custom DH with SHA2
  6. ecdh-sha2-nistp256: ECDH over NIST P-256 with SHA2
  7. ecdh-sha2-nistp384: ECDH over NIST P-384 with SHA2
  8. ecdh-sha2-nistp521: ECDH over NIST P-521 with SHA2

We have to look at 3 things here:

  • ECDH curve choice:
    This eliminates 6-8 because NIST curves suck.
    They leak secrets through timing side channels and off-curve inputs.
    Also, NIST is considered harmful and cannot be trusted.
  • Bit size of the DH modulus:
    This eliminates 2 because the NSA has supercomputers and possibly unknown attacks.
    1024 bits simply don’t offer sufficient security margin.
  • Security of the hash function:
    This eliminates 2-4 because SHA1 is broken.
    We don’t have to wait for a second preimage attack that takes 10 minutes on a cellphone to disable it right now.

We are left with 1 and 5.
1 is better and it’s perfectly OK to only support that but for interoperability (with Eclipse, WinSCP), 5 can be included.

Recommended /etc/ssh/sshd_config snippet:


Recommended /etc/ssh/ssh_config snippet:

# Github needs diffie-hellman-group-exchange-sha1 some of the time but not always.
#    KexAlgorithms,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
Host *

If you chose to enable 5, open /etc/ssh/moduli if exists, and delete lines where the 5th column is less than 2000.

awk '$5 > 2000' /etc/ssh/moduli > "${HOME}/moduli"
wc -l "${HOME}/moduli" # make sure there is something left
mv "${HOME}/moduli" /etc/ssh/moduli

If it does not exist, create it:

ssh-keygen -G /etc/ssh/moduli.all -b 4096
ssh-keygen -T /etc/ssh/ -f /etc/ssh/moduli.all
mv /etc/ssh/ /etc/ssh/moduli
rm /etc/ssh/moduli.all

This will take a while so continue while it’s running.


The key exchange ensures that the server and the client shares a secret no one else knows.
We also have to make sure that they share this secret with each other and not an NSA analyst.

Server authentication

The server proves its identity to the client by signing the key resulting from the key exchange.
There are 4 public key algorithms for authentication:

  1. DSA with SHA1
  2. ECDSA with SHA256, SHA384 or SHA512 depending on key size
  3. Ed25519 with SHA512
  4. RSA with SHA1

DSA keys must be exactly 1024 bits so let’s disable that.
Number 2 here involves NIST suckage and should be disabled as well.
Another important disadvantage of DSA and ECDSA is that it uses randomness for each signature.
If the random numbers are not the best quality, then it is possible to recover the secret key.
Fortunately, RSA using SHA1 is not a problem here because the value being signed is actually a SHA2 hash.
The hash function SHA1(SHA2(x)) is just as secure as SHA2 (it has less bits of course but no better attacks).

Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

The first time you connect to your server, you will be asked to accept the new fingerprint.

This will also disable the horribly broken v1 protocol that you should not have enabled in the first place.
We should remove the unused keys and only generate a large RSA key and an Ed25519 key.
Your init scripts may recreate the unused keys.
If you don’t want that, remove any ssh-keygen commands from the init script.

cd /etc/ssh
rm ssh_host_*key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N "" < /dev/null

Client authentication

The client must prove its identity to the server as well.
There are various methods to do that.

The simplest is password authentication.
This should be disabled immediately after setting up a more secure method because it allows compromised servers to steal passwords.
Password authentication is also more vulnerable to online bruteforce attacks.

Recommended /etc/ssh/sshd_config snippet:

PasswordAuthentication no
ChallengeResponseAuthentication no

Recommended /etc/ssh/ssh_config snippet:

Host *
    PasswordAuthentication no
    ChallengeResponseAuthentication no

The most common and secure method is public key authentication, basically the same process as the server authentication.

Recommended /etc/ssh/sshd_config snippet:

PubkeyAuthentication yes

Recommended /etc/ssh/ssh_config snippet:

Host *
    PubkeyAuthentication yes

Generate client keys using the following commands:

ssh-keygen -t ed25519 -o -a 100
ssh-keygen -t rsa -b 4096 -o -a 100

You can deploy your new client public keys using ssh-copy-id.

It is also possible to use OTP authentication to reduce the consequences of lost passwords.
Google Authenticator is a nice implementation of TOTP, or Timebased One Time Password.
You can also use a printed list of one time passwords or any other PAM module, really, if you enable ChallengeResponseAuthentication.

User Authentication

Even with Public Key authentication, you should only allow incoming connections from expected users. The AllowUsers setting in sshd_config lets you specify users who are allowed to connect, but this can get complicated with a large number of ssh users. Additionally, when deleting a user from the system, the username is not removed from sshd_config, which adds to maintenance requirements. The solution is to use the AllowGroups setting instead, and add users to an ssh-user group.

Recommended /etc/ssh/sshd_config snippet:

AllowGroups ssh-user

Create the ssh-user group with sudo groupadd ssh-user, then add each ssh user to the group with sudo usermod -a -G ssh-user <username>.

Symmetric ciphers

Symmetric ciphers are used to encrypt the data after the initial key exchange and authentication is complete.

Here we have quite a few algorithms:

  1. 3des-cbc
  2. aes128-cbc
  3. aes192-cbc
  4. aes256-cbc
  5. aes128-ctr
  6. aes192-ctr
  7. aes256-ctr
  10. arcfour
  11. arcfour128
  12. arcfour256
  13. blowfish-cbc
  14. cast128-cbc

We have to consider the following:

  • Security of the cipher algorithm:
    This eliminates 1 and 10-12 – both DES and RC4 are broken.
    Again, no need to wait for them to become even weaker, disable them now.
  • Key size:
    At least 128 bits, the more the better.
  • Block size:
    Does not apply to stream ciphers.
    At least 128 bits.
    This eliminates 13 and 14 because those have a 64 bit block size.
  • Cipher mode:
    The recommended approach here is to prefer AE modes and optionally allow CTR for compatibility.
    CTR with Encrypt-then-MAC is provably secure.

Chacha20-poly1305 is preferred over AES-GCM because the SSH protocol does not encrypt message sizes when GCM (or EtM) is in use.
This allows some traffic analysis even without decrypting the data.
We will deal with that soon.

Recommended /etc/ssh/sshd_config snippet:


Recommended /etc/ssh/ssh_config snippet:

Host *

Message authentication codes

Encryption provides confidentiality, message authentication code provides integrity.
We need both.
If an AE cipher mode is selected, then extra MACs are not used, the integrity is already given.
If CTR is selected, then we need a MAC to calculate and attach a tag to every message.

There are multiple ways to combine ciphers and MACs – not all of these are useful.
The 3 most common:

  • Encrypt-then-MAC: encrypt the message, then attach the MAC of the ciphertext.
  • MAC-then-encrypt: attach the MAC of the plaintext, then encrypt everything.
  • Encrypt-and-MAC: encrypt the message, then attach the MAC of the plaintext.

Only Encrypt-then-MAC should be used, period.
Using MAC-then-encrypt have lead to many attacks on TLS while Encrypt-and-MAC have lead to not quite that many attacks on SSH.
The reason for this is that the more you fiddle with an attacker provided message, the more chance the attacker has to gain information through side channels.
In case of Encrypt-then-MAC, the MAC is verified and if incorrect, discarded.
Boom, one step, no timing channels.
In case of MAC-then-encrypt, first the attacker provided message has to be decrypted and only then can you verify it.
Decryption failure (due to invalid CBC padding for example) may take less time than verification failure.
Encrypt-and-MAC also has to be decrypted first, leading to the same kind of potential side channels.
It’s even worse because no one said that a MAC’s output can’t leak what its input was.
SSH by default, uses this method.

Here are the available MAC choices:

  1. hmac-md5
  2. hmac-md5-96
  3. hmac-ripemd160
  4. hmac-sha1
  5. hmac-sha1-96
  6. hmac-sha2-256
  7. hmac-sha2-512
  8. umac-64
  9. umac-128

The selection considerations:

  • Security of the hash algorithm:
    No MD5 and SHA1.
    Yes, I know that HMAC-SHA1 does not need collision resistance but why wait?
    Disable weak crypto today.
  • Encrypt-then-MAC:
    I am not aware of a security proof for CTR-and-HMAC but I also don’t think CTR decryption can fail.
    Since there are no downgrade attacks, you can add them to the end of the list.
    You can also do this on a host by host basis so you know which ones are less safe.
  • Tag size:
    At least 128 bits.
    This eliminates umac-64-etm.
  • Key size:
    At least 128 bits.
    This doesn’t eliminate anything at this point.

Recommended /etc/ssh/sshd_config snippet:


Recommended /etc/ssh/ssh_config snippet:

Host *

Preventing key theft

Even with forward secrecy the secret keys must be kept secret.
The NSA has a database of stolen keys – you do not want your key there.

System hardening

OpenSSH has some undocumented, and rarely used features.
UseRoaming is one such feature with a known vulnerability.

Recommended /etc/ssh/ssh_config snippet:

Host *
   UseRoaming no

This post is not intended to be a comprehensive system security guide.
Very briefly:

  • Don’t install what you don’t need:
    Every single line of code has a chance of containing a bug.
    Some of these bugs are security holes.
    Fewer lines, fewer holes.
  • Use free software:
    As in speech.
    You want to use code that’s actually reviewed or that you can review yourself.
    There is no way to achieve that without source code.
    Someone may have reviewed proprietary crap but who knows.
  • Keep your software up to date:
    New versions often fix critical security holes.
  • Exploit mitigation:
    Sad but true – there will always be security holes in your software.
    There are things you can do to prevent their exploitation, such as GCC’s -fstack-protector.
    One of the best security projects out there is Grsecurity.
    Use it or use OpenBSD.

Traffic analysis resistance

Set up Tor hidden services for your SSH servers.
This has multiple advantages.
It provides an additional layer of encryption and server authentication.
People looking at your traffic will not know your IP, so they will be unable to scan and target other services running on the same server and client.
Attackers can still attack these services but don’t know if it has anything to do with the observed traffic until they actually break in.

Now this is only true if you don’t disclose your SSH server’s fingerprint in any other way.
You should only accept connections from the hidden service or from LAN, if required.

If you don’t need LAN access, you can add the following line to /etc/ssh/sshd_config:


Add this to /etc/tor/torrc:

HiddenServiceDir /var/lib/tor/hidden_service/ssh
HiddenServicePort 22

You will find the hostname you have to use in /var/lib/tor/hidden_service/ssh/hostname.
You also have to configure the client to use Tor.
For this, socat will be needed.
Add the following line to /etc/ssh/ssh_config:

Host *.onion
    ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050

Host *

If you want to allow connections from LAN, don’t use the ListenAddress line, configure your firewall instead.

Key storage

You should encrypt your client key files using a strong password.
Additionally, you can use ssh-keygen -o -a $number to slow down cracking attempts by iterating the hash function many times.
You may want to store them on a pendrive and only plug it in when you want to use SSH.
Are you more likely to lose your pendrive or have your system compromised?
I don’t know.

Unfortunately, you can’t encrypt your server key and it must be always available, or else sshd won’t start.
The only thing protecting it is OS access controls.

The end

It’s probably a good idea to test the changes.
ssh -v will print the selected algorithms and also makes problems easier to spot.
Be extremely careful when configuring SSH on a remote host.
Always keep an active session, never restart sshd.
Instead you can send the SIGHUP signal to reload the configuration without killing your session.
You can be even more careful by starting a new sshd instance on a different port and testing that.

Can you make these changes?
If the answer is yes, then…

NSA Happy Dance

If the answer is no, it’s probably due to compatibility problems.
You can try to convince the other side to upgrade their security and turn it into a yes.
I have created a wiki page where anyone can add config files for preserving compatibility with various SSH implementations and SSH based services.

If you work for a big company and change management doesn’t let you do it, I’m sorry.
I’ve seen the v1 protocol enabled in such places.
There is no chance of improvement.
Give up to preseve your sanity.

Special thanks to the people of Twitter for the improvements.


You may have noticed that this document changed since last time.
I want to be very transparent about this.
There were three major changes:

  • After some debate and going back and forth between including GCM or not, it’s now back again.
    The reason for dropping it was that SSH doesn’t encrypt packet sizes when using GCM.
    The reason for bringing it back is that SSH does the same with any EtM algorithms.
    There is no way around this unless you can live with chacha20-poly1305 only.
    Also, the leaked documents don’t sound like they can figure out the lengths or confirm presence of some things, more like straight up “send it to us and we’ll decrypt it for you”.
    Wrapping SSH in a Tor hidden service will take care of any traffic analysis concerns.
  • I’m now allowing Encrypt-and-MAC algorithms with CTR ciphers as a last resort.
    I initially thought it was possible to use downgrade attacks, I now think it is not.
  • I briefly disabled RSA because it uses SHA1, this turned out to be a non-issue because we’re signing SHA2 hashes.

You can see the full list of changes on github.
I promise not to use git push -f.

OpenVPN for paranoids

Victor Dorneanu

Continuing my admin series this time I’d like to setup a VPN using OpenVPN as user-based VPN solution. Unlike IPSec solutions which require IPSec on both (server and client) sides, securing the VPN tunnel by OpenSSL is a more preferable option.

In this post I’ll try to show which steps have to be taken in order to:

  • secure the communication channel
  • use up-to-date (and secure!) TLS configurations
  • prevent information leaks when the VPN tunnel is down

At least for the last one some additional steps are required to route your traffic only through the VPN tunnel. As a client you don’t want your connection to be “downgraded” (in terms of security) without even realizing it. That’s why you might want to restrict your routes and allow outbound connection only through the (virtual) interface dedicated to the VPN. How this is done and which methods exist, is covered later on.


Create certificates

In the last post I’ve already created the VPN CA and also issued certificates for server and client.

My solution is more a DIY one. If you want to use a more convient one, have a look at easy-rsa.

Configure VPN server

There are several steps aimed at successfully configuring your OpenVPN server.

Basic configuration

  • Add new user openvpn
root@debian:/etc/openvpn# useradd openvpn
  • Specify which interface the server should listen on
# Which local IP address should OpenVPN
# listen on? (optional)
;local a.b.c.d
  • Specify protocol and port OpenVPN should initiate connections over
# Which TCP/UDP port should OpenVPN listen on?
# If you want to run multiple OpenVPN instances
# on the same machine, use a different port
# number for each one.  You will need to
# open up this port on your firewall.
port 443

# TCP or UDP server?
;proto tcp
proto udp
  • Specify VPN subnet where to assign IP addresses to clients from
# Configure server mode and supply a VPN subnet
# for OpenVPN to draw client addresses from.
# The server will take for itself,
# the rest will be made available to clients.
# Each client will be able to reach the server
# on Comment this line out if you are
# ethernet bridging. See the man page for more info.

Secure communication channel

Add DH params

root@debian:/etc/openvpn# openssl dhparam -out dh2048.pem 2048
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time

And now add it to the config file:

# Diffie hellman parameters.
# Generate your own with:
#   openssl dhparam -out dh2048.pem 2048
dh /etc/openvpn/dh2048.pem

HMAC firewall using tls-auth

root@debian:/etc/openvpn# openvpn --genkey --secret ta.key

And add it to the config file:

# For extra security beyond that provided
# by SSL/TLS, create an "HMAC firewall"
# to help block DoS attacks and UDP port flooding.
# Generate with:
#   openvpn --genkey --secret ta.key
# The server and each client must have
# a copy of this key.
# The second parameter should be '0'
# on the server and '1' on the clients.
tls-auth /etc/openvpn/ta.key 0 # This file is secret

Strong cryptographic cipher

First let’s have a look at the available ciphers (filter only those with 256 bit key length:

root@debian:/etc/openvpn# openvpn --show-ciphers | grep 256
AES-256-CBC 256 bit default key (fixed)
AES-256-OFB 256 bit default key (fixed) (TLS client/server mode)
AES-256-CFB 256 bit default key (fixed) (TLS client/server mode)
AES-256-CFB1 256 bit default key (fixed) (TLS client/server mode)
AES-256-CFB8 256 bit default key (fixed) (TLS client/server mode)
CAMELLIA-256-CBC 256 bit default key (fixed)
CAMELLIA-256-CFB 256 bit default key (fixed) (TLS client/server mode)
CAMELLIA-256-CFB1 256 bit default key (fixed) (TLS client/server mode)
CAMELLIA-256-CFB8 256 bit default key (fixed) (TLS client/server mode)
CAMELLIA-256-OFB 256 bit default key (fixed) (TLS client/server mode)

I’ll select AES-256-CBC:

# Select a cryptographic cipher.
# This config item must be copied to
# the client config file as well.
;cipher BF-CBC        # Blowfish (default)
;cipher AES-128-CBC   # AES
;cipher DES-EDE3-CBC  # Triple-DES
cipher AES-256-CBC

Select TLS cipher

In order to guarantee FPS I’ll be using a Diffie–Hellman key exchange-based PFS like DHE-[…] or an elliptic curve Diffie–Hellman-based PFS like ECDHE-[…]. As stated here OpenVPN does not support TLS-ECDHE-* or more exotic cipher-suites as there is no elliptic curve support currently.

Let’s have a look at the available TLS ciphers:

root@debian:/etc/openvpn# openvpn --show-tls | grep TLS-DHE

Add some ciphers to the config file:

# Select a TLS cipher

Additionally you can specify which TLS version should be used

# Use TLS 1.2 as minimum requirement
tls-version-min 1.2

Use SHA2 for message authentication

In case you don’t have performance issues, change the the MAC digest to:

auth SHA512

Verify revoked client certs

Also make sure that no client with a revoked certificate is allowed to connect to the VPN server:

crl-verify path-to/your-ca-crl.pem

Route all client traffic (incl. DNS) through VPN tunnel

push "redirect-gateway def1"

Pushing this option to the clients will route all client originating traffic through the OpenVPN server. The server however must know how to deal with this traffic by NATing it to the Internet or passing it to some proxy. DNS traffic will be routed as well. You may want to push some DNS server to the clients, such as:

push "dhcp-option DNS"
push "dhcp-option DNS"

Make other subnets available to the clients

In order to allow VPN clients to access subnets behind the VPN-gateway you’ll have to advertise these subnets to the clients. One example:

# Push routes to the client to allow it
# to reach other private subnets behind
# the server.  Remember that these
# private subnets will also need
# to know to route the OpenVPN client
# address pool (
# back to the OpenVPN server.
push "route"

More on Routing in the section below.

Harden server

Move it to chroot

In a chroot environment a process/daemon would not be able to access any part of the system’s filesystem except for the directory it is currently in.

root@debian:/etc/openvpn# mkdir -p /home/openvpn/tmp
root@debian:/etc/openvpn# chown -R openvpn:openvpn /home/openvpn

Also add to the config file:

# Lock down daemon to chroot jail
chroot jail

Don’t run as root

Reduce OpenVPN’s server privileges:

# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
# You can uncomment this out on
# non-Windows systems.
user openvpn
group openvpn

Unprivileged mode

While being able to operate on a tun device, the OpenVPN daemon should be able to access it in an unprivileged mode. Internally sudo is being used to call iproute which will apply the interface properties and add/delete/modify routing information. For getting this to work I’ll use the described steps in the official documentation:

  • Create a new script
root@debian:/etc/openvpn# cat /usr/local/sbin/unpriv-ip 
sudo /sbin/ip $*
root@debian:/etc/openvpn# chmod a+x /usr/local/sbin/unpriv-ip
  • Allow user1 to execute /sbin/ip (in /etc/sudoers):
# Allow user1 nobody to execute /sbin/ip
openvpn ALL=(ALL)  NOPASSWD: /sbin/ip
  • Change OpenVPN configuration
# Set  alternate command to execute instead of default iproute2 command.
iproute /usr/local/sbin/unpriv-ip

Check file permissions

Also check the file permissions for the file inside /etc/openvpn:

root@debian:/etc/openvpn# chmod go-rwx /etc/openvpn/ta.key /etc/openvpn/dh2048.pem /etc/openvpn/certs/raspberry_pi.p12

Disable password caching

You might get some warning like

WARNING: this configuration may cache passwords in memory — use the auth-nocache option to prevent this

Then add it fo the conf:

# Prevent password caching

Start server

Let’s give it a try:

root@debian:/etc/openvpn# openvpn server.conf 


Tue Nov 17 17:30:16 2015 Control Channel Authentication: using 'ta.key' as a OpenVPN static key file
Tue Nov 17 17:30:16 2015 Outgoing Control Channel Authentication: Using 512 bit message hash 'SHA512' for HMAC authentication
Tue Nov 17 17:30:16 2015 Incoming Control Channel Authentication: Using 512 bit message hash 'SHA512' for HMAC authentication
Tue Nov 17 17:30:16 2015 Socket Buffers: 
Tue Nov 17 17:30:16 2015 ROUTE_GATEWAY IFACE=eth0 HWADDR=b8:27:eb:5c:0a:5d
Tue Nov 17 17:30:16 2015 TUN/TAP device tun0 opened
Tue Nov 17 17:30:16 2015 TUN/TAP TX queue length set to 100
Tue Nov 17 17:30:16 2015 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
Tue Nov 17 17:30:16 2015 /usr/local/sbin/unpriv-ip link set dev tun0 up mtu 1500
Tue Nov 17 17:30:16 2015 /usr/local/sbin/unpriv-ip addr add dev tun0 local peer
Tue Nov 17 17:30:17 2015 /usr/local/sbin/unpriv-ip route add via
Tue Nov 17 17:30:17 2015 chroot to '/home/openvpn' and cd to '/' succeeded
Tue Nov 17 17:30:17 2015 GID set to openvpn
Tue Nov 17 17:30:17 2015 UID set to openvpn
Tue Nov 17 17:30:17 2015 Initialization Sequence Completed

So everything seemed to work. Let’s check some things:

  • Process owner
root@debian:/home/victor# ps -efl | grep openvpn
4 S openvpn   9930  1633  0  80   0 -  1356  e0778 17:30 pts/1    00:00:00 openvpn server.conf
  • Opened files
root@debian:/home/victor# lsof | grep 9930
openvpn    9930         openvpn  cwd       DIR      179,2     4096        101 /home/openvpn
openvpn    9930         openvpn  rtd       DIR      179,2     4096        101 /home/openvpn

  • Connectivity
root@debian:/home/openvpn# netstat -uptan | grep 443
udp        0   *                           9930/openvpn

Looks good.

Configure client

Basic configuration

Let’s add the basic stuff:

  • Specify we’re operating in client mode
# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
  • Specify TUN/TAP device for the client
 Use the same setting as you are using on
# the server.
# On most systems, the VPN will not function
# unless you partially or fully disable
# the firewall for the TUN/TAP interface.
;dev tap
dev tun
  • Connection details
# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
;proto tcp
proto udp

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
;remote my-server-1 1194
remote 443

Secure communication channel

  • Specify previously generated client certificate and key
 SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
ca vpn-ca.crt
cert victor.crt
key victor.key
  • Verify server certificate
# Verify server certificate by checking that the
# certicate has the correct key usage set.
# This is an important precaution to protect against
# a potential attack discussed here:
# To use this feature, you will need to generate
# your server certificates with the keyUsage set to
#   digitalSignature, keyEncipherment
# and the extendedKeyUsage to
#   serverAuth
# EasyRSA can do this for you.
remote-cert-tls server
  • Verify server’s CN
verify-x509-name 'C=NU,, Root CA,' subject
  • Use tls-auth key (make sure you use the same one as on the server)
# If a tls-auth key is used on the server
# then every client must also have the key.
tls-auth ta.key 1
  • Use SHA2 as MAC
auth SHA512
  • Select cryptographic cipher (same as on the server)
# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
cipher cipher AES-256-CFB

Test connection

  • Initial try (with errors, see below)
OpenVPN 2.3_git x86_64-unknown-linux-gnu built on Jun 11 2015
library versions: OpenSSL 1.0.2d 9 Jul 2015, LZO 2.09
Enter Private Key Password: ******************
VERIFY ERROR: depth=2, error=self signed certificate in certificate chain: C=NU,, Root CA, Root CA
OpenSSL: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
TLS_ERROR: BIO read tls_read_plaintext error
TLS Error: TLS object -> incoming plaintext read error
TLS Error: TLS handshake failed

We can see that the certificate verification has failed. So the client is not able to verify the certificate presented by the server because it doesn’t have the root cert. Let’s adapt the config:

# SSL/TLS parms.
ca vpn-ca-chain.pem

Give it another try:

OpenVPN 2.3_git x86_64-unknown-linux-gnu  built on Jun 11 2015
library versions: OpenSSL 1.0.2d 9 Jul 2015, LZO 2.09
NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Enter Private Key Password: ******************
WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Control Channel Authentication: using 'ta.key' as a OpenVPN static key file
Outgoing Control Channel Authentication: Using 512 bit message hash 'SHA512' for HMAC authentication
Incoming Control Channel Authentication: Using 512 bit message hash 'SHA512' for HMAC authentication
TCP/UDP: Preserving recently used remote address:vpn-server>:80
Socket Buffers: 
UDP link local: (not bound)
UDP link remote: 
TLS: Initial packet from sid=d4f744bb e391d690
VERIFY OK: depth=2, C=NU,, Root CA, Root CA
VERIFY OK: depth=1, C=NU,, Root CA, CA
Validating certificate key usage
++ Certificate has key usage  00a0, expects 00a0
Validating certificate extended key usage
++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
VERIFY X509NAME OK: C=NU, ST=/dev/null, L=/dev/random,, OU=VPN,
VERIFY OK: depth=0, C=NU, ST=/dev/null, L=/dev/random,, OU=VPN,
Data Channel Encrypt: Cipher 'AES-256-CBC' initialized with 256 bit key
Data Channel Encrypt: Using 512 bit message hash 'SHA512' for HMAC authentication
Data Channel Decrypt: Cipher 'AES-256-CBC' initialized with 256 bit key
Data Channel Decrypt: Using 512 bit message hash 'SHA512' for HMAC authentication
Control Channel: TLSv1.2, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA256, 4096 bit RSA
[vpn.xxxxx] Peer Connection Initiated with ;vpn-server>:80
SENT CONTROL [vpn.xxxxx]: 'PUSH_REQUEST' (status=1)
PUSH: Received control message: 'PUSH_REPLY,route,redirect-gateway def1,dhcp-option DNS,dhcp-option DNS,route,topology net30,ping 10,ping-restart 120,ifconfig'
OPTIONS IMPORT: timers and/or timeouts modified
OPTIONS IMPORT: --ifconfig/up options modified
OPTIONS IMPORT: route options modified
OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
ROUTE_GATEWAY IFACE=wlan0 HWADDR=3c:77:e6:18:f9:65
TUN/TAP device tun0 opened
TUN/TAP TX queue length set to 100
do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
/usr/bin/ip link set dev tun0 up mtu 1500
/usr/bin/ip addr add dev tun0 local peer
/etc/openvpn/update-resolv-conf tun0 1500 1602 init

/usr/bin/ip route add <vpn-server>/32 via
/usr/bin/ip route add via
/usr/bin/ip route add via
/usr/bin/ip route add via
/usr/bin/ip route add via
Initialization Sequence Completed

Looks good. What about the server?

  • Server logs
TLS: Initial packet from [AF_INET], sid=230b4633 1fb1bfae
VERIFY OK: depth=2, C=NU,, Root CA, Root CA
VERIFY OK: depth=1, C=NU,, Root CA, CA
VERIFY OK: depth=0, C=NU, ST=/dev/null, L=/dev/random,,, CN=Victor Dorneanu
Data Channel Encrypt: Cipher 'AES-256-CFB' initialized with 256 bit key
Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Data Channel Decrypt: Cipher 'AES-256-CFB' initialized with 256 bit key
Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Control Channel: TLSv1.2, cipher TLSv1/SSLv3 DHE-RSA-AES256-GCM-SHA384, 4096 bit RSA
[Victor Dorneanu] Peer Connection Initiated with [AF_INET]
Victor Dorneanu/ MULTI_sva: pool returned IPv4=, IPv6=(Not enabled)
Victor Dorneanu/ MULTI: Learn: -> Victor Dorneanu/
Victor Dorneanu/ MULTI: primary virtual IP for Victor Dorneanu/
Victor Dorneanu/ PUSH: Received control message: 'PUSH_REQUEST'
Victor Dorneanu/ send_push_reply(): safe_cap=940
Victor Dorneanu/ SENT CONTROL [Victor Dorneanu]: 'PUSH_REPLY,route,topology net30,ping 10,ping-restart 120,ifconfig' (status=1)


  • Port scanning
$ sudo nmap -sU -p 443 

Starting Nmap 6.47 ( ) at 2015-11-11 20:24 CET
Nmap scan report for debian.local (
Host is up (0.00048s latency).
443/tcp closed https
MAC Address: 52:54:00:E5:01:E4 (QEMU Virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 0.14 seconds

So tls-auth seems to work.


    client              [shape = "cisco.pc"];
    internet            [shape = "cloud"];
    client -- internet;
    internet -- gw;
    gw [label = "Server"];
    #internet -- gw1;
    #internet -- gw;
    network vpn-net {
        address = ""
        gw        [address = ".1", shape = cisco.vpn_gateway];
        #victor    [address = ".4", shape = cisco.pc];
    network home-net {
        address = ""
        gw        [address = ".2"];
        #router    [address = ".1", label = "R", class = obj_router];
        raspberry [address = ".24", label = "Laptop", class = obj_workstation];
        storage   [address = ".25", label = "Storage", class = obj_storage];    

We have a typical road-warrior use case where a single client connects to a remote subnet using a VPN. Afer sucessfully establishing the VPN connection the client will be part of the vpn-net subnet:

    network vpn-net {
        address = ""
        gw        [address = ".1", shape = cisco.vpn_gateway];
        client    [address = ".4", shape = cisco.pc];
    network home-net {
        address = ""
        gw        [address = ".2"];
        #router    [address = ".1", label = "R", class = obj_router];
        raspberry [address = ".24", label = "Laptop", class = obj_workstation];
        storage   [address = ".25", label = "Storage", class = obj_storage];    

Having advertised the network address of home-net the client should be able to access Laptop ( or Storage ( Also keep in mind that the client will be able to access the whole range. You may want to add client-specific access policies.

By passing client’s traffic through the OpenVPN server you’ll need to implement NATing in order to let your clients access the Internet or other subnets.

root@debian:/# iptables -t nat -A POSTROUTING -s -o eth0 -j MASQUERADE

Client based attack vectors

Regardless the countermeasures taken to secure the server, as a client you want your VPN connection to be safe and secure. In a hostile environment like a coffee shop or on any security conferences you want to keep your data safe from any curios eyes. Using a VPN no one could have a look at at the data inside the “stream” but there are some problems you should be aware of.

An attacker could bring down your VPN connection by spoofing the server and sending you TCP packets with a RST flag inside it. As a consequence this might destroy the virtual interface which in turn will remove all routing rules previously added by the OpenVPN client regarding that specific interface. Afterwards you will be using your physical interface without any further protection. And the worst thing about it: You won’t even notice it!

As found on and there are several methods how to increase client security either by using firewall rules or routing tables. I’ll have a look at both.


Even though your VPN provider will “push” to the clients a trust DNS server, the DHCP server might override this information causing the client to use an untrusted DNS server. In that case the retrieval of DNS information over DHCP should be avoided. Hard-coding an IP address of a trusted DNS server like is recommended.

The client will get the DNS information from the server, however the /etc/resolv.conf has to be adapted as well. I’ve found some hook script which will modify your resolv.conf with the information from the server. On Arch Linux there is an AUR package as well. After installing the hook script, also change the client config file to make this work:

script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

After connecting to the server, you should see sth like this:

Mon Nov 16 14:05:45 2015 /etc/openvpn/update-resolv-conf tun0 1500 1570 init
push "dhcp-option DNS"
push "dhcp-option DNS"

The update-resolv-conf is now called from another script (see below). The config file should now look like this:

# Run scripts after tunnel is up or down
up "./ -u"
down "./ -d"

Denial of Service

In the case of our VPN connection DoS attacks would bring down the TCP stream which in turn will cause the virtual interface go down and finally also removing all routing information. In the worst case the client won’t have any protection at all (otherwise provided by the VPN tunnel). But first let’s have a look at what happens when a client connects to the VPN server:

1) Fri Nov 13 13:17:13 2015 /usr/bin/ip link set dev tun0 up mtu 1500
2) Fri Nov 13 13:17:13 2015 /usr/bin/ip addr add dev tun0 local peer
3) Fri Nov 13 13:17:13 2015 /usr/bin/ip route add xx.xx.xx.xx/32 via
4) Fri Nov 13 13:17:13 2015 /usr/bin/ip route add via
5) Fri Nov 13 13:17:13 2015 /usr/bin/ip route add via
6) Fri Nov 13 13:17:13 2015 /usr/bin/ip route add via
7) Fri Nov 13 13:17:13 2015 /usr/bin/ip route add via

Obviously the VPN client did following steps:

  1. Set the MTU for the virtual device (tun0)
  2. Set the virtual client ( and the server endpoints (
  3. Add a static routing rule for the VPN server over Prevents the encrypted VPN traffic from being sent via the VPN itself.
  4. and cover the entire IPv4 IP address pool. This will basically route all traffic to the Internet through (tun0)
  5. The home-net subnet ( should also be routable over tun0
  6. Route for the server IP address in the vpn-net subnet

Now if a DHCP server pushes a subnet mask for a bigger subnet then this will mask/override the masks from the VPN server. So in some cases the routing information from the DHCP server will be more specific than the OpenVPN routes. For example

/usr/bin/ip route add via

will be more specific than:

/usr/bin/ip route add via
/usr/bin/ip route add via

I’ve found some ways how to prevent this kind of attacks. On a Linux based system one could use different routing tables or harden firewall rules to restrict connection outside the VPN tunnel.

Andrew was to use multiple routing tables (I didn’t even know one could do that) by putting the OpenVPN routes into a dedicated routing table. So basically we’ll add routing information that say:

  1. If a packet is destinated to the OpenVPN server, use the main table
  2. All other packets should use the OpenVPN table

This way you’ll keep your OpenVPN routes safe from the DHCP ones. Using /usr/bin/ip we will add some rules in the routing policy database and do what is called policy routing. The rules are being stored in a RPDB (routing policy database). The RPDB controls in which order the kernel search through the routing tables.

According to the man page (ip-rule(8)):

Each policy routing rule consists of a selector and an action predicate. The RPDB is scanned in order of
decreasing priority. The selector of each rule is applied to {source address, destination address, incoming
interface, tos, fwmark} and, if the selector matches the packet, the action is performed. The action predi‐
cate may return with success. In this case, it will either give a route or failure indication and the RPDB
lookup is terminated. Otherwise, the RPDB program continues with the next rule.

Also have a look at for some useful examples.

Add rules to the RPDB

At startup time the kernel configures the default RPDB consisting of three rules (from the man page):

  1. Priority: 0, Selector: match anything, Action: lookup routing table local (ID 255). The local table is a special routing table containing high priority control routes for local and broadcast addresses. Rule 0 is special. It cannot be deleted or overridden.
  2. Priority: 32766, Selector: match anything, Action: lookup routing table main (ID 254). The main table is the normal routing table containing all non-policy routes. This rule may be deleted and/or overridden with other ones by the administrator.
  3. Priority: 32767, Selector: match anything, Action: lookup routing table default (ID 253). The default table is empty. It is reserved for some post-processing if no previous default rules selected the packet. This rule may also be deleted.

Let’s have a look at the configuration:

/usr/bin/ip rule add to <openvpn-server> table main pref 1000    (1)
/usr/bin/ip rule add to <openvpn-server> unreachable pref 1001   (2)
/usr/bin/ip rule add table 94 pref 1002                          (3)
/usr/bin/ip rule add unreachable pref 1003                       (4)

By using preferences numbers we can ensure that the rules are prioritized correctly. Now some explanations

  1. The first 2 rules [(1) and (2)] apply to packets whose destination is the IP address of the OpenVPN server.
  2. The 2nd rule prevents VPN server packets being routed through the VPN tunnel itself (in the case the main routing table is empty)
  3. The 3rd command defines a new routing table (whose id is 94)
  4. The last rules prevents packets from using the main table in case the OpenVPN table (id = 94) is empty.

Let’s have a look at the IP rule policy after the rules have been added:

$ ip rule
0:    from all lookup local 
1000:    from all to <server IP addr> lookup main 
1001:    from all to <server IP addr> unreachable
1002:    from all lookup 94 
1003:    from all unreachable
32766:    from all lookup main 
32767:    from all lookup default

In order of priority the rules say:

  1. All traffic destinated to the should lookup for routing information in table main
  2. All other traffic should lookup for routing information in table 94.

So let’s try that out! Here are routes for table main:

$ ip route show
default via dev wlan0  proto static  metric 600 dev wlan0  proto kernel  scope link  src  metric 600

Although there is a default route in the main table, packets shouldn’t be able to be sent because we have not defined yet any routes for table 94:

$ ping
connect: Network is unreachable

After removing the IP rules:

/usr/bin/ip rule del to <openvpn-server>table main pref 1000
/usr/bin/ip rule del to <openvpn-server> unreachable pref 1001
/usr/bin/ip rule del table 94 pref 1002
/usr/bin/ip rule del unreachable pref 1003

… everything is back to normal:

$ ping -c 3
PING ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=53 time=27.8 ms
64 bytes from ( icmp_seq=2 ttl=53 time=32.1 ms
64 bytes from ( icmp_seq=3 ttl=53 time=30.4 ms

--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 27.817/30.167/32.187/1.804 ms

Adding routes to the OpenVPN table

In the next steps OpenVPN should add its routing information to the previously created routing table and not the main one.

/sbin/ip route add table 94 dev tun0 via
/sbin/ip route add table 94 dev tun0 via

Now you review the routing information in table 94:

$ ip route show table 94  
default via dev tun0 via dev tun0 dev tun0  proto kernel  scope link  src

Andrew wrote some hook script you can download here. Save this to you machine and make it executable:

# wget
# cp route /usr/local/bin/route
# chmod a+x /usr/local/bin/route

Now the client config file has to be modified:

route-up /usr/local/bin/route

The server config has to be modified as well by removing the remote-gateway option:

# push "redirect-gateway def1"


This solution seems to be very clever, however I’ve had performance issues and also multiple routing problems. Perhaps will somebody see and comment what I’m doing wrong.

Use of firewall rules

Uncomplicated Firewall (ufw)

I’ll be using ufw for setting up my firewall. First add these lines to /etc/ufw/before.rules before the “filer* line:

# NAT (Network Address Translation) table rules

# Allow traffic from clients to enp1s0

# Don't delete these required lines, otherwise there will be errors

Now enable the firewall:

# ufw enable
Firewall is active and enabled on system startup
# ufw status
Status: active

… add some ufw rules:

SERVER=`host <vpn-server> | awk '{ print $4; }'`

# Default policies
ufw default deny incoming
ufw default deny outgoing

# OpenVPN interface (adjust interface accordingly to your configuration)
ufw allow in on tun0
ufw allow out on tun0

# Deny any TCP/UDP connections on wlan0
ufw deny out on wlan0
ufw deny in on wlan0

# Allow local LAN on wlan0 (adjust ip accordingly to your configuration)
ufw allow in on wlan0 from
ufw allow out on wlan0 to

# Over wlan0 allow only traffic to VPN server (:80/udp)
ufw allow in on wlan0 from $SERVER port 80 proto udp
ufw allow out on wlan0 from $SERVER port 80 proto udp

ufw allow in from any to any port 53
ufw allow out from any to any port 53

Check that:

$ ufw status verbose
Status: active

To                         Action      From
--                         ------      ----
Anywhere on tun0           ALLOW       Anywhere
Anywhere on wlan0          DENY        Anywhere
Anywhere on wlan0          ALLOW
Anywhere on wlan0          ALLOW       <vpn-server> 80/udp
53                         ALLOW       Anywhere

Anywhere                   ALLOW OUT   Anywhere on tun0
Anywhere                   DENY OUT    Anywhere on wlan0             ALLOW OUT   Anywhere on wlan0
Anywhere                   ALLOW OUT   <vpn-server> 80/udp on wlan0
53                         ALLOW OUT   Anywhere

The initialization script called by OpenVPN uses iptables. But feel free to adapt if you want to stick with ufw.

Using iptables (prefered)

If you don’t want any fancy firewall frameworks, you can of course stick to iptables.

# VPN server address

# Local LAN subnet

# Interface where your local LAN is accessibble

# The VPN virtual interface

# Do NATing from VPN interface to gateway interface
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -A POSTROUTING -s $VPN_LAN -o $GW_INT -j MASQUERADE

# Allow all traffic on VPN interface
iptables -A OUTPUT -o $VPN_INT -j ACCEPT
iptables -A INPUT  -i $VPN_INT -j ACCEPT

# Allow traffic to/from VPN server
iptables -A INPUT  -i $GW_INT -s $VPN_SERVER -p udp --sport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $GW_INT -d $VPN_SERVER -p udp --dport 80 -m state --state ESTABLISHED -j ACCEPT

# Allow local traffic
iptables -A INPUT  -i $GW_INT -s $LOCAL_LAN -d $LOCAL_LAN -j ACCEPT

# Define here other exceptions
# ...

# Deny all traffic on gateway interface by default
iptables -A INPUT -i $GW_INT -j DROP
iptables -A OUTPUT -o $GW_INT -j DROP

# Block IPv6 traffic
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP

All these rules are part of this script which is called by OpenVPN (up/down commands):

# Run scripts after tunnel is up or down
up "./ -u"
down "./ -d"

Have a look at the script and add your own actions to be executed when the tunnel is up or down. Also make sure you save the script in the same directory where the configuration files resides.

That’t it! Now you should have no leaks if your VPN is down. Let’s check that out

  • Before establishing the VPN tunnel
$ ping -c 4
PING ( 56(84) bytes of data.
--- ping statistics ---
0 packets transmitted, 0 received
  • After establishing the VPN
$ ping -c 4
PING ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=50 time=122 ms
64 bytes from ( icmp_seq=2 ttl=50 time=83.8 ms
64 bytes from ( icmp_seq=3 ttl=50 time=82.6 ms
--- ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms

OpenSSH “/etc/ssh/moduli” file

Philip Eklöf

While playing around with a small and customized Debian based system, I noticed that the following log message was seen every time a user logged on via SSH:

WARNING: /etc/ssh/moduli does not exist, using fixed modulus

So what is this moduli file and why should you keep one of those around?


As moduli(5) explains it: The /etc/ssh/moduli file contains prime numbers and generators for use by sshd(8) in the Diffie-Hellman Group Exchange key exchange method.

The Diffi-Hellman key exchange is used in the beginning of SSH sessions to generate a shared secret between the client and the server. Obviously, it would be quite important to get that step right.

Static modulus

But if my system was missing this file, which modulus was then used and sent to the connecting client? The log message said “using fixed modulus”. That sounds like something static. If you’d snoop around a bit in OpenSSH’s source code, you’d find a function called dh_new_group14() in dh.c:

DH *
static char *gen = "2", *group14 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"

return (dh_new_group_asc(gen, group14));

That sure looks like a (6*10+4)*4*8 = 2048 bit value.

As the prime number is one of the non-secret values in the DH key exchange, meaning that the value is sent as plain text over the net, it should be simple to verify whether this is the value that is in use or not. Wireshark comes handy:

The “DH modulus (P)” value obviously looks the same as the characters in the code snippet above (prefixing null byte excluded). This was also fully confirmed by fetching the whole value as a text string and comparing both sources.

Should one be worried about this static built-in DH prime? Is it insecure? The ordinary moduli file is almost the same thing though, a static file provided by the OpenSSH project. These primes are known and most systems on the Internet are probably using the same set.

To perform a secure DH key exchange you’d need good primes, but not unique ones. The unique part of DH is within the random values generated by the two different parties (client/server), combined with the prime, this ends up as the shared secret.

Modulus length

The /etc/ssh/moduli file usually contains several different entries and sshd picks one randomly for each session. Does this increase security in some way?

The file also contains entries of different lengths in the range of 1024 to 8192 bits. I would probably not want to use the 1024 bit ones. Further investigation shows that the connecting SSH client specifies which minimum and maximum bit lengths it accepts, but also which bit length it prefers:

hex 400 = dec 1024, hex 1000 = 4096 dec, hex 2000 = dec 8192

You see that “DH GEX Numbers of Bits” set to 4096? That means that the ssh client I was using prefers 4096 bits. Hopefully, that was a well-thought-out decision made by some clever OpenSSH developer. Taking this into account, the static built-in prime, used if the /etc/ssh/moduli file is missing, ought to be considered too short.

BTW, this information is also seen by running ssh with the verbose flag:
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<4096<8192) sent

Generating the moduli file

Lets get hold of one of those moduli files with 4096 bit modulus then. Using the ssh-keygen tool you may generate it yourself.

First, “candidate primes” needs to be generated:
ssh-keygen -G /tmp/4096.1 -b 4096
It ends up as over 10000 candidates.

Secondly, these are tested and only the safe ones are kept; about 30 entries, at least in this run. The output file contains the ready-to-use moduli file.
ssh-keygen -T /tmp/4096.2 -f /tmp/4096.1

About four hours of CPU time was needed to complete this process on an Intel i7 processor. Generating 1024 bit ones instead only needed 1-2 minutes. As previously mentioned, the default moduli file contains varying sizes, even including 8192 bit entries. No wonder this file is pre-generated.

Trying it out

The new moduli file was installed and Wireshark was fired up once more:

Fetch the value off Wireshark and quickly process it in bash.
# p=00:da:11:08:47:31:4b:53:75:39:f2:a2:06:81:21:2a:0b:2e:.....

Strip all colons, erase first two characters (the null byte) and finally make the whole text string upper case:
# p=${p//:}; p=${p:2}; p=${p^^}

Finally find out if there’s a matching entry in the moduli file:
# grep " $p$" /etc/ssh/moduli | sed -r 's/ [^ ]+$//'
20140208234044 2 6 100 4095 2
Yup. There sure is.

Giving it another try, another ssh and Wireshark session, shows that another modulus was used this time:
20140209012047 2 6 100 4095 2


Keep in mind that I am definitely not a mathematician nor a crypto expert. But should you really be using the default pre-generated moduli file that comes along with your Linux distribution?

  • You will find 1024 bit entries in there. Do you really want to allow that? Some broken (?) SSH client might have set its preferred bit length, or its max bit length to 1024 bit.

  • Is there any chance that these entries could have been tampered with? Have they been carefully chosen to make some sort of cracking easier? Checking out OpenSSH’s CVS history of the moduli file, certainly shows that the file has been re-generated several times the last couple of years.

  • As almost everyone out there would be using the same set of DH primes, is it possible that an adversary could have built some sort of database that makes DH cracking easier, in case these specific primes are used in the DH key exchange?

  • There seems to be some sort of benefit of not always performing the DH key exchange using the same prime. Otherwise, why would sshd not just use the first entry in the moduli file all the time? If this is the case, would you really want to use the same primes as all the others do?


EDIT (2015-01-06):

Due to recent Edward Snowden leaks, this article was recently published.

The article is a walkthrough of the various encryption related settings provided by sshd, including recommendations on what to enable or not. Regarding the different key exchange algorithms, the article mentions:

“Bit size of the DH modulus: This eliminates 2 [diffie-hellman-group1-sha1: 1024 bit DH with SHA1] because the NSA has supercomputers and possibly unknown attacks. 1024 bits simply don’t offer sufficient security margin.”

Obviously, that doesn’t really prove anything, but it is interesting that the modulus length is mentioned, and that it is recommended to remove the 1024 bit primes from the moduli file.

5 Free VPN Clients

OpenVPN is an open source VPN server that’s easy to set up for use with open source VPN clients. You can easily export configuration files from OpenVPN to import into a variety of open source and commercial clients. OpenVPN is also integrated into several router firmware packages including popular DD-WRT, OpenWRT, and Tomato. The OpenVPN system isn’t compatible with popular commercial VPN providers, but it provides an open source and free alternative for setting up VPNs to expensive and closed commercial models.

Cisco VPN (Windows/Mac/Linux, Variable Cost)

Cisco has a high market saturation in corporate and educational environments, and for many of you, any experience you’ve had with virtual private networks is through such exposure. The price to run a Cisco VPN is highly variable—and you can’t even get a concrete number without a quote from the company—but you can, as an end user, download the free Cisco VPN client for Windows and Mac—though many readers complained about the lack of 64-bit support in the free Cisco client.

LogMeIn Hamachi (Windows/Mac/Linux, Free)

Hamachi’s strongest attribute is its ease of use. If you’ve read some of the other entries in the Hive Five and realized that you don’t want a contract for a corporate VPN or the hassle of configuring a bunch of routers with open-source firmware packages, and you just want to set up a simple virtual network between you and your friend, your phone, or your office, Hamachi offers nearly instant deployment. Install the Hamachi client on all the machines and devices you want to connect into your network and add them to your Hamachi VPN and you’re done. It’s dead simple. The downside, if you’re concerned about it, is that your VPN isn’t locally managed—it’s centrally managed by Hamachi through their servers.

Shrew Soft (Windows/Linux, Free)

Shrew Soft offers a VPN that, while popular in its own right, received quite a boost when people started adopting Windows 7 64-bit in droves and found that Cisco wasn’t in any hurry to release a 64-bit client to accommodate them. Shrew Soft works with a variety of VPN server protocols including IPsec, OpenSWAN, freeSWAN, and strongSWAN.

Windows Built-In VPN (Windows, Free)

Windows has a built-in VPN client. Surprised? Many people are. It’s not a heavily advertised feature, but it covers many people’s needs. Before exploring other client solutions, it’s worth pulling up the quick launch box in the Windows start menu and typing “VPN” to start the configuration process. In Windows versions prior to Windows Vista, the built-in VPN client received a fair amount of criticism for lacking features and supported protocols. Since Vista and especially in the Windows 7 implementation, it’s grown significantly and unless you need a feature or standard that isn’t implemented you may not need to install anything at all.

5 free and secure messaging tools

1: ChatSecure

ChatSecure (Figure A) is an open source chat app for both Android and iOS that uses Off-the-Record (OTR) Messaging over XMMP. You can use this app to chat via your preexisting accounts (Google Chat, Facebook Chat, VKontakte, Yandex, Hyves, Odnoklassniki, StudiVZ, Livejournal, Jabber, and more).

It allows you to set a master password to keep prying eyes out of the chat app itself, supports WiFi Mesh Chat (chatting with others on the same local wireless or mesh network ─ no server required), and even enables you to create anonymous “burner” chat accounts. If you have to do anonymous chatting, and you’re behind a firewall, you can install the Orbot proxy tool, which will get you through. (Orbot is also required to create “burner” accounts.) With ChatSecure, two-way encryption cannot take place until a user has been verified (done through the app). Once verified, you can encrypt conversations and each sent message will indicate if it is encrypted or not.

2: Cryptocat

Cryptocat (Figure B) is a secure open source messaging extension for the Google Chrome browser. All messages are encrypted before they leave your computer, so there’s no concern that plain text is being sent and then encrypted on a third-party server.

One interesting Cryptocat feature is the ability to join what is called the “lobby.” Within the lobby you can chat with any other Cryptocat users who happen to be hanging out. To start a chat, you enter a name for the chat, create a username, and click Connect. Once you’re in, tell the other users the name of the chat room and have them join. Cryptocat is a bit of a nod to old school IRC chats, but it gets the job done quickly and easily.

3: Surespot Encrypted Messenger

Surespot Encrypted Messenger (Figure C) is an end-to-end symmetric encryption messaging tool (using 256-bit AES-GCM encryption) that creates keys using 521 bit ECDH shared secret derivation. It’s private — period. The best thing about Surespot is that all the privacy is built-in, so you won’t even notice the security layer.

When you first run Surespot, you create a username and password. It is important that you not forget this password, as there is no way to recover it. You’ll also want to back up your Surespot identity once created. If you don’t do this, and you need to re-install the app, you won’t be able to log back into your Surespot account. With this locked down system, it’s nearly impossible for someone to steal your Surespot identity. One nice touch is that you can’t even take a screenshot of an in-progress chat.

Surespot is free, but you can purchase an encrypted voice messaging feature. (It’s free to receive and play messages; it costs only to record and send voice). The cost for the voice is $1.99 USD and is an in-app purchase. Surespot is available for both Android and iOS.

4: Tox

Tox is somewhat new to the world of secure chatting. It was created as a reaction to concerns of Skype’s privacy (or lack thereof). Tox uses dispersed networking and strong cryptography to create a secure (using NaCl crypto library) messaging system for everyone. Users are assigned a private and public key and connect to one another directly — no middleman or third party involved.

With Tox, you can do text, phone, and video, all secure. Tox is free, open source, and available on Linux, Windows, and Mac. Its interface is incredibly easy to use (anyone of any skill level can start using right away) and doesn’t require you to connect with your Facebook, Google, Twitter, or any other account.

5: ChatCrypt

ChatCrypt (Figure E) offers another nod to old-school chatting tools, with a web-based system that encrypts all messages before they leave the browser (so they can’t be read on the server side). You enter the site, create a room and username, set a password for the room, share the password to anyone you want to join, and start chatting.

Figure E

The system works by utilizing the AES-256 algorithm in CTR mode. So long as the secret (strong ─ hint, hint) password created for the chat doesn’t end up in the hands of the wrong people, the chat will go off securely and no information will be leaked. The only caveat with ChatCrypt, is that you get text chatting only. But at least you can invite as many people as necessary into the chat.

Weak Diffie-Hellman and the Logjam Attack

key exchange
is a popular cryptographic algorithm
that allows Internet protocols to agree on a shared
key and negotiate a secure connection. It is
fundamental to many protocols including HTTPS, SSH,
IPsec, SMTPS, and protocols that rely on TLS.

We have uncovered several weaknesses in how
Diffie-Hellman key exchange has been deployed:

  1. Logjam attack against the TLS protocol.
    The Logjam attack allows a man-in-the-middle
    attacker to downgrade vulnerable TLS connections to
    512-bit export-grade cryptography. This allows the
    attacker to read and modify any data passed over the
    connection. The attack is reminiscent of
    the FREAK
    , but is due to a flaw in the TLS protocol
    rather than an implementation vulnerability, and
    attacks a Diffie-Hellman key exchange rather than an
    RSA key exchange. The attack affects any server that
    supports DHE_EXPORT ciphers, and affects
    all modern web browsers. 8.4% of the Top 1 Million
    domains were initially vulnerable.

  2. Threats from state-level adversaries.
    Millions of HTTPS, SSH, and VPN servers all use the
    same prime numbers for Diffie-Hellman key
    exchange. Practitioners believed this was safe as
    long as new key exchange messages were generated for
    every connection. However, the first step in the
    number field sieve—the most efficient
    algorithm for breaking a Diffie-Hellman
    connection—is dependent only on this prime.
    After this first step, an attacker can quickly break
    individual connections.

    We carried out this computation against the most
    common 512-bit prime used for TLS and demonstrate
    that the Logjam attack can be used to downgrade
    connections to 80% of TLS servers
    supporting DHE_EXPORT. We further estimate
    that an academic team can break a 768-bit prime and
    that a nation-state can break a 1024-bit
    prime. Breaking the single, most common 1024-bit
    prime used by web servers would allow passive
    eavesdropping on connections to 18% of the Top 1
    Million HTTPS domains. A second prime would allow
    passive decryption of connections to 66% of VPN
    servers and 26% of SSH servers. A close reading of
    published NSA leaks shows that the agency’s attacks
    on VPNs are consistent with having achieved such a

Full Technical Paper

Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice

David Adrian, Karthikeyan Bhargavan, Zakir Durumeric,
Pierrick Gaudry, Matthew Green, J. Alex Halderman, Nadia
Heninger, Drew Springall, Emmanuel Thomé, Luke
Valenta, Benjamin VanderSloot, Eric Wustrow, Santiago
Zanella-Béguelin, and Paul Zimmermann
22nd ACM Conference on Computer and Communications Security (CCS ’15), Denver, CO, October 2015
Best Paper Award Winner

More: Full paper |
Talk slides |

Additional Information

We have also created
a Guide to Deploying Diffie-Hellman for TLS, and
several Proof of Concept Demos.

Contact the Team

This study was performed by computer scientists at
CNRS, Inria Nancy-Grand Est, Inria Paris-Rocquencourt,
Microsoft Research, Johns Hopkins University, University
of Michigan, and the University of Pennsylvania:
David Adrian,
Karthikeyan Bhargavan,
Zakir Durumeric,
Pierrick Gaudry,
Matthew Green,
J. Alex Halderman,
Nadia Heninger,
Drew Springall,
Emmanuel Thomé,
Luke Valenta,
Benjamin VanderSloot,
Eric Wustrow,
Santiago Zanella-Beguelin, and
Paul Zimmermann.
The team can be contacted at

Who is Affected?

Websites, mail servers, and other TLS-dependent
services that support DHE_EXPORT ciphers are
at risk for the Logjam attack. We use
Internet-wide scanning
to measure who is vulnerable.

Protocol Vulnerable to Logjam
HTTPS — Top 1 Million Domains 8.4%
HTTPS — Browser Trusted Sites 3.4%
SMTP+StartTLS — IPv4 Address Space 14.8%
POP3S — IPv4 Address Space 8.9%
IMAPS — IPv4 Address Space 8.4%

Websites that use one of a few commonly shared
1024-bit Diffie-Hellman groups may be susceptible to
passive eavesdropping from an attacker with
nation-state resources. Here, we show how various
protocols would be affected if a single 1024-bit group
were broken in each protocol, assuming a typical
up-to-date client (e.g., most recent version of
OpenSSH or up-to-date installation of Chrome).

Vulnerable if most common 1024-bit group is broken
HTTPS — Top 1 Million Domains 17.9%
HTTPS — Browser Trusted Sites 6.6%
SSH — IPv4 Address Space 25.7%
IKEv1 (IPsec VPNs) — IPv4 Address Space 66.1%

What Should I Do?

If you run a server…

If you have a web or mail server, you should
disable support for export cipher suites and use a
2048-bit Diffie-Hellman group. We have published
a Guide to Deploying
Diffie-Hellman for TLS
with step-by-step
instructions. If you use SSH, you should upgrade both
your server and client installations to the most
recent version of OpenSSH, which prefers
Elliptic-Curve Diffie-Hellman Key Exchange.

If you use a browser…

Make sure you have the most recent version of your
browser installed, and check for updates
frequently. Google Chrome (including Android Browser),
Mozilla Firefox, Microsoft Internet Explorer, and
Apple Safari are all deploying fixes for the Logjam

If you’re a sysadmin or developer …

Make sure any TLS libraries you use are up-to-date,
that servers you maintain use 2048-bit or larger
primes, and that clients you maintain reject
Diffie-Hellman primes smaller than 1024-bit.

These results were first made public on May 20, 2015;
peer-reviewed conference paper published October 13, 2015.

Frozenstar Domain Keys Identified Mail (DKIM)

Frozenstar mail system has implemented OpenDKIM.
DomainKeys Identified Mail (DKIM) is a method for E-mail authentication, allowing a person who receives email to verify that the message actually comes from the domain that it claims to have come from. The need for this type of authentication arises because spam often has forged headers.

DKIM uses public-key cryptography to allow the sender to electronically sign legitimate emails in a way that can be verified by recipients.

DKIM also guards against tampering with mail, offering almost end-to-end integrity from a signing to a verifying Mail transfer agent (MTA).

Key generation for dkim-milter and its setup with DNS

The opendkim-tools package provides a tool, opendkim-genkey for creating your key pairs:

opendkim-genkey -t -s mail -d

This will generate two files: mail.private which is your private key, and mail.txt which is your DNS record containing your public key.

The -s argument supplies the selector (in our case “mail”), the -d argument supplies the domain, and the -t argument says that we are running DKIM in test mode. This indicates that verifiers shouldn’t drop your mail if something’s wrong with the signature. Its seems that the majority using DKIM run it in test mode.

Copy your private key in place:

cp mail.private /etc/mail/dkim.key

Now create your DNS record as supplied in mail.txt, which should look like this, that’s frozenstar domainkeys:

 201701._domainkey	IN	TXT	( "v=DKIM1; h=rsa-sha256; k=rsa; s=email; "
	  "VbQ0tq2iGj/iP9gJwLNMQWPAHJjUuXXkVKGZ9uP2n21AoXUlWD2iz7mfwbEOZNLuSSkCwGrLciymQYvQg712SnhbTTd+OoMZMuufbGxXyLDgRBStNdnADkIdfDGS2lE+Sfg++9hijJKe/n/gcJen2d5f407HsMx3T6+3RDAmoLvTkUmklPe3JuciU5ntIhR6HyntgvajMiGSTNuWR9csrnJoew82U2Y8pzsCAwEAAQ==" )  ; ----- DKIM key 201701 for

Introduction to OTR

Off-the-Record Messaging OTR adds end-to-end encryption for chat messages. It has many features:

  • Encryption All the encryption takes place on your devices. This protects your conversation from being read by others, even over insecure networks and untrusted chat providers.
  • Authentication You know if the person is who they say they are.
  • Perfect forward secrecy If you lose control of your private keys, no previous conversation is compromised.
  • Deniability The messages you send do not have digital signatures that are checkable by a third party. Anyone can forge messages after a conversation to make them look like they came from you. However, during a conversation, your correspondent is assured the messages she sees are authentic and unmodified.

Installing OTR

In this tutorial, we will be using OTR with pidgin. Pidgin has the most mature implementation of OTR, and runs on Windows, Linux, and Mac.


  1. Press Alt+F2 and run:
  2. Copy the following line into the new terminal window and hit Enter:
    sudo apt-get install pidgin-otr
  3. To Run Pidgin press Alt+F2 and type:




Pidgin can be run on the Mac, but it is much easier to run Adium instead. Adium is a native port of pidgin to the Mac OS. Download Adium.

Adding an Account to Pidgin

Check out our pidgin tutorial for instructions on adding your account to pidgin.

Setting up OTR

Now with both Pidgin and OTR installed

  • Select Tools > Plugins from the main window
  • Enable Off-The-Record Messaging plugin and click the Configure button
  • Select your account from the list and click Generate
  • IMPORTANT NOTE!: Under “Default OTR Settings” select both Require private messaging and Don’t log OTR conversations. This guarantees that you only have encrypted conversations and that you aren’t logging your past conversations. Remember that it is always possible for the person you are talking with to log the conversation. It is a good idea to ask whether that person logs OTR conversations.

Adding Buddies to your Contacts

  • To add a Buddy, from the main Pidgin window select Buddies > Add Buddy.
  • Make sure to select your account and to spell your buddy’s username correctly when filling it in. You have the option of creating groups to categorize your buddies.
  • Click Add.
  • Once your buddies have been added and are available to chat they will appear in the main pidgin window. To start chatting double-click on a buddy’s username from the list.

Authenticate Buddies

Click Start private conversation and follow the instructions to authenticate each other to start a private conversation. The easiest method to authenticate someone is the Question and Answer method in which you ask the other person a question that only they could answer. This is an important security step to verify that you are talking to who you think you are talking to. Examples of acceptable questions:

Q: What did you and I talk about at Jad’s last night in the front room? (lower case, one word)
A: welding

There was just the two people involved in the past conversation, so this is a secure question.

Q: Who created the poster on the wall of my bedroom? (lower case, two words)
A: beehive collective

This is a secure question assuming you trust the people that have been in your bedroom.

Questions like “What is my hair color” or “What’s my dog’s name” are insecure because most anyone could easily discover the answers to those questions.