diff --git a/REFERENCE.md b/REFERENCE.md
index 35e339f7..48e7683a 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -451,6 +451,8 @@ The following parameters are available in the `openvpn::client` defined type:
* [`remote_host`](#remote_host)
* [`cipher`](#cipher)
* [`tls_cipher`](#tls_cipher)
+* [`data_ciphers`](#data_ciphers)
+* [`data_ciphers_fallback`](#data_ciphers_fallback)
* [`resolv_retry`](#resolv_retry)
* [`auth_retry`](#auth_retry)
* [`verb`](#verb)
@@ -575,6 +577,22 @@ TLS Ciphers to use
Default value: `'TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256'`
+##### `data_ciphers`
+
+Data type: `String`
+
+Ciphers to allow for packet encryption
+
+Default value: `'AES-256-GCM:AES-128-GCM'`
+
+##### `data_ciphers_fallback`
+
+Data type: `String`
+
+Cipher that is used to fall back to if OpenVPN cannot determine which cipher the peer is willing to use.
+
+Default value: ``undef``
+
##### `resolv_retry`
Data type: `String`
@@ -1012,6 +1030,8 @@ The following parameters are available in the `openvpn::server` defined type:
* [`verb`](#verb)
* [`cipher`](#cipher)
* [`tls_cipher`](#tls_cipher)
+* [`data_ciphers`](#data_ciphers)
+* [`data_ciphers_fallback`](#data_ciphers_fallback)
* [`persist_key`](#persist_key)
* [`persist_tun`](#persist_tun)
* [`key_expire`](#key_expire)
diff --git a/manifests/client.pp b/manifests/client.pp
index 69bff018..19c833cc 100644
--- a/manifests/client.pp
+++ b/manifests/client.pp
@@ -14,6 +14,8 @@
# @param remote_host The IP or hostname of the openvpn server service.
# @param cipher Cipher to use for packet encryption
# @param tls_cipher TLS Ciphers to use
+# @param data_ciphers Ciphers to allow for packet encryption
+# @param data_ciphers_fallback Cipher to use if peer cipher config cannot be determined
# @param resolv_retry How many seconds should the openvpn client try to resolve the server's hostname
# @param auth_retry Controls how OpenVPN responds to username/password verification errors such as the client-side response to an AUTH_FAILED message from the server or verification failure of the private key password.
# @param verb Level of logging verbosity
@@ -61,6 +63,8 @@
Boolean $pam = false,
String $cipher = 'AES-256-GCM',
String $tls_cipher = 'TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256',
+ String $data_ciphers = 'AES-256-GCM:AES-128-GCM',
+ String $data_ciphers_fallback = undef,
Boolean $authuserpass = false,
Hash $setenv = {},
Hash $setenv_safe = {},
diff --git a/manifests/server.pp b/manifests/server.pp
index 5a0a7a06..428c1bec 100644
--- a/manifests/server.pp
+++ b/manifests/server.pp
@@ -71,6 +71,8 @@
# @param verb Level of logging verbosity
# @param cipher Cipher to use for packet encryption
# @param tls_cipher TLS Ciphers to use
+# @param data_ciphers Ciphers to allow for packet encryption
+# @param data_ciphers_fallback Cipher to use if peer cipher config cannot be determined
# @param persist_key Try to retain access to resources that may be unavailable because of privilege downgrades
# @param persist_tun Try to retain access to resources that may be unavailable because of privilege downgrades
# @param key_expire The number of days to certify the server certificate for
@@ -225,6 +227,8 @@
Optional[String] $verb = undef,
String $cipher = 'AES-256-GCM',
String $tls_cipher = 'TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256',
+ String $data_ciphers = 'AES-256-GCM:AES-128-GCM',
+ String $data_ciphers_fallback = undef,
Boolean $persist_key = false,
Boolean $persist_tun = false,
Boolean $tls_auth = false,
diff --git a/spec/defines/openvpn_client_spec.rb b/spec/defines/openvpn_client_spec.rb
index 99e6d731..b3b72a16 100644
--- a/spec/defines/openvpn_client_spec.rb
+++ b/spec/defines/openvpn_client_spec.rb
@@ -152,6 +152,8 @@
'persist_tun' => false,
'cipher' => 'AES-256-GCM',
'tls_cipher' => 'TLS-DHE-RSA-WITH-AES-256-CBC-SHA',
+ 'data_ciphers' => 'AES-256-GCM',
+ 'data_ciphers_fallback' => 'AES-128-GCM',
'port' => '123',
'proto' => 'udp',
'remote_host' => %w[somewhere galaxy],
@@ -187,6 +189,8 @@
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^setenv_safe\s+FORWARD_COMPATIBLE\s+1$}) }
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^cipher\s+AES-256-GCM$}) }
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^tls-cipher\s+TLS-DHE-RSA-WITH-AES-256-CBC-SHA$}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^data-ciphers\s+AES-256-GCM$}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^data-ciphers-fallback\s+AES-128-GCM$}) }
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^tls-client$}) }
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^verify-x509-name\s+"test_server"\s+name$}) }
it { is_expected.to contain_file("#{server_directory}/test_server/download-configs/test_client/test_client.conf").with_content(%r{^sndbuf\s+393216$}) }
diff --git a/spec/defines/openvpn_server_spec.rb b/spec/defines/openvpn_server_spec.rb
index a7fcc539..0db9d344 100644
--- a/spec/defines/openvpn_server_spec.rb
+++ b/spec/defines/openvpn_server_spec.rb
@@ -409,6 +409,8 @@
'verb' => 'mute',
'cipher' => 'DES-CBC',
'tls_cipher' => 'TLS-DHE-RSA-WITH-AES-256-CBC-SHA',
+ 'data_ciphers' => 'AES-256-GCM',
+ 'data_ciphers_fallback' => 'AES-128-GCM',
'persist_key' => true,
'persist_tun' => true,
'duplicate_cn' => true,
@@ -449,6 +451,8 @@
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^management\s+1.3.3.7 1337$}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^verb mute$}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^cipher DES-CBC$}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^data-ciphers\s+AES-256-GCM$}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^data-ciphers-fallback\s+AES-128-GCM$}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^tls-cipher\s+TLS-DHE-RSA-WITH-AES-256-CBC-SHA$}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^persist-key$}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^persist-tun$}) }
@@ -569,6 +573,8 @@
'verb' => 'mute',
'cipher' => 'DES-CBC',
'tls_cipher' => 'TLS-DHE-RSA-WITH-AES-256-CBC-SHA',
+ 'data_ciphers' => 'AES-256-GCM',
+ 'data_ciphers_fallback' => 'AES-128-GCM',
'persist_key' => true,
'persist_tun' => true,
'duplicate_cn' => true,
@@ -687,6 +693,8 @@
it { is_expected.not_to contain_file("#{server_directory}/test_server.conf").with_content(%r{verb}) }
it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{cipher AES-256-GCM}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^data-ciphers\s+AES-256-GCM$}) }
+ it { is_expected.to contain_file("#{server_directory}/test_server.conf").with_content(%r{^data-ciphers-fallback\s+AES-128-GCM$}) }
it { is_expected.not_to contain_file("#{server_directory}/test_server.conf").with_content(%r{persist-key}) }
it { is_expected.not_to contain_file("#{server_directory}/test_server.conf").with_content(%r{persist-tun}) }
it { is_expected.not_to contain_file("#{server_directory}/test_server.conf").with_content(%r{^duplicate-cn$}) }
@@ -957,6 +965,8 @@
'verb' => 'mute',
'cipher' => 'DES-CBC',
'tls_cipher' => 'TLS-DHE-RSA-WITH-AES-256-CBC-SHA',
+ 'data_ciphers' => 'AES-256-GCM',
+ 'data_ciphers_fallback' => 'AES-128-GCM',
'persist_key' => true,
'persist_tun' => true,
'duplicate_cn' => true,
diff --git a/templates/client.erb b/templates/client.erb
index 679cf1a8..2088a696 100644
--- a/templates/client.erb
+++ b/templates/client.erb
@@ -28,6 +28,12 @@ cipher <%= @cipher %>
<% if @tls_cipher != '' -%>
tls-cipher <%= @tls_cipher %>
<% end -%>
+<% if @data_ciphers != 'AES-256-GCM:AES-128-GCM' -%>
+data-ciphers <%= @data_ciphers %>
+<% end -%>
+<% if @data_ciphers_fallback -%>
+data-ciphers-fallback <%= @data_ciphers_fallback %>
+<% end -%>
<% if @mute_replay_warnings -%>
mute-replay-warnings
<% end -%>
diff --git a/templates/server.erb b/templates/server.erb
index e9036a0c..9e2f06db 100644
--- a/templates/server.erb
+++ b/templates/server.erb
@@ -138,6 +138,12 @@ cipher <%= @cipher %>
<% if @tls_cipher != '' -%>
tls-cipher <%= @tls_cipher %>
<% end -%>
+<% if @data_ciphers != 'AES-256-GCM:AES-128-GCM' -%>
+data-ciphers <%= @data_ciphers %>
+<% end -%>
+<% if @data_ciphers_fallback -%>
+data-ciphers-fallback <%= @data_ciphers_fallback %>
+<% end -%>
<% if @c2c -%>
client-to-client
<% end -%>