Bug #8087
openProvide Calling-Station-ID to RADIUS backed VPN connections
0%
Description
I'm using Duo 2fa radius proxy to connect to the on board RADIUS server in PFsense and am not getting an IP or a username in the Duo Notifications. This is a much valued feature to validate that the request is coming from one of my machines (I'm not always there when secneg occurs). I do not know the RADIUS attribute for username.
Updated by Jim Pingle over 5 years ago
- Category set to Authentication
Might not be possible to put the client address in there since I am not sure the auth system will see that from OpenVPN/IPsec, but it might be worth looking into.
There have been changes since this request was made, however. It does fill in the NAS-IP-Address (configurable in the auth server settings) and NAS-Identifier, which will show at least which firewall the request came through.
Updated by Viktor Gurov almost 5 years ago
Calling-Station-Id is already supported by EAP-RADIUS strongswan plugin, see https://wiki.strongswan.org/projects/strongswan/wiki/EAPRadius#Attributes-sent-to-RADIUS-servers
testing packet capture:
Attribute Value Pairs AVP: t=User-Name(1) l=6 val=test AVP: t=NAS-Port-Type(61) l=6 val=Virtual(5) AVP: t=Service-Type(6) l=6 val=Framed(2) AVP: t=NAS-Port(5) l=6 val=18 AVP: t=NAS-Port-Id(87) l=12 val=con-mobile AVP: t=NAS-IP-Address(4) l=6 val=192.168.3.4 AVP: t=Called-Station-Id(30) l=19 val=192.168.3.4[4500] AVP: t=Calling-Station-Id(31) l=20 val=192.168.3.3[54552] AVP: t=EAP-Message(79) l=11 Last Segment[1] AVP: t=NAS-Identifier(32) l=12 val=strongSwan AVP: t=Message-Authenticator(80) l=18 val=e782d4fcf522e54f87db557dfb529a0f
in case of OpenVPN, the current implementation of openvpn-plugin-auth-script.so do not support $clientid environment variable
Updated by Brandon Verkada over 2 years ago
Has there been any update on this? Ran into the same issue, pfSense OpenVPN not forwarding the Radius parameters to DUO.
Updated by Christian Ullrich over 2 years ago
OpenVPN makes the client's apparent address available in environment variables:
--- openvpn.auth-user.php.orig 2022-12-03 14:08:05.556382000 +0100
+++ openvpn.auth-user.php 2022-12-03 14:08:34.276103000 +0100
@@ -102,7 +102,7 @@
$attributes = array("nas_identifier" => "openVPN",
"nas_port_type" => RADIUS_VIRTUAL,
"nas_port" => $_GET['nas_port'],
- "calling_station_id" => get_interface_ip() . ":" . $_GET['nas_port']);
+ "calling_station_id" => getenv("untrusted_ip") . ":" . getenv("untrusted_port"));
foreach ($authmodes as $authmode) {
$authcfg = auth_get_authserver($authmode);
Updated by Brandon Verkada over 2 years ago
Christian Ullrich wrote in #note-4:
OpenVPN makes the client's apparent address available in environment variables:
[...]
Thanks Christian. I patched the openvpn.auth-user.php but had to change it a bit, skipping the untrusted_port part, otherwise DUO won't parse the IP parameter correctly. It may be a DUO-related issue only, not sure.
So what ended up working for me is replacing the whole line with:
"calling_station_id" => getenv("untrusted_ip"));
Updated by Brandon Verkada about 1 year ago
Welp, even "my" last hack stopped working somewhere along the pfSense stable upgrade path, currently on "23.09.1-RELEASE (amd64)" and the `calling_station_id` doesn't get populated with `untrusted_ip` (although present when tcpduming the openvpn client stream), the `untrusted_port` does propagate correctly though. Weird.
"calling_station_id" => getenv("untrusted_ip") . ":" . getenv("untrusted_port"));
If anyone has a solution it would be much appreciated.
Updated by Erich Weiler about 1 month ago
Just a followup on this item... I also would love for this to work. I can verify that @Brandon Verkada is right, it seems like "untrusted_port" seems to be available in the pfSense php scripts, but "untrusted_ip" doesn't seem to work. I verified in the OpenVPN 2.6 docs that "untrusted_ip" is indeed a valid environment variable, as documented here:
https://openvpn.net/community-resources/reference-manual-for-openvpn-2-6/
It seems these scripts are pulling in several other environment variables such as "username", "password", "common_name" and "untrusted_port", but I can't seem to get it to pull in "untrusted_ip". I think it's probably a simple fix somewhere to import this environment variable into the openvpn.auth-user.php script... Does anyone know how we can do that? It would make dozens of people in my organization extremely happy... :)
Updated by Brandon Verkada about 1 month ago
We have three patches now that do the trick:
- duofix.sh
#!/bin/sh
patch -b /etc/inc/openvpn.attributes.php openvpn.attributes.php.patch
patch -b /etc/inc/openvpn.auth-user.php openvpn.auth-user.php.patch
patch -b /usr/local/sbin/ovpn_auth_verify_async ovpn_auth_verify_async.patch
- openvpn.attributes.php.patch
--- /etc/inc/openvpn.attributes.php 2024-02-14 01:26:06.236903000 -0800
+++ /etc/inc/openvpn.attributes.php.duofix 2024-02-14 01:26:28.982237000 -0800
@@ -21,7 +21,7 @@
* limitations under the License.
*/
-global $attributes, $username, $dev, $untrusted_port;
+global $attributes, $username, $dev, $untrusted_port, $untrusted_ip;
if (empty($dev)) {
$dev = "openvpn";
- openvpn.auth-user.php.patch
--- /etc/inc/openvpn.auth-user.php 2024-02-14 01:11:18.732283000 -0800
+++ /etc/inc/openvpn.auth-user.php.duofix 2024-02-14 01:22:49.415374000 -0800
@@ -36,7 +36,7 @@
/* setup syslog logging */
openlog("openvpn", LOG_ODELAY, LOG_AUTH);
-global $common_name, $username, $dev, $untrusted_port;
+global $common_name, $username, $dev, $untrusted_port, $untrusted_ip;
if (isset($_GET['username'])) {
$authmodes = explode(",", base64_decode($_GET['authcfg']));
@@ -48,6 +48,7 @@
$strictusercn = $_GET['strictcn'] == "false" ? false : true;
$dev = $_GET['dev'];
$untrusted_port = $_GET['untrusted_port'];
+ $untrusted_ip = $_GET['untrusted_ip'];
} else {
/* read data from environment */
$username = getenv("username");
@@ -55,6 +56,7 @@
$common_name = getenv("common_name");
$dev = getenv("dev");
$untrusted_port = getenv("untrusted_port");
+ $untrusted_ip = getenv("untrusted_ip");
}
if (!$username) {
@@ -102,7 +104,7 @@
$attributes = array("nas_identifier" => "openVPN",
"nas_port_type" => RADIUS_VIRTUAL,
"nas_port" => $_GET['nas_port'],
- "calling_station_id" => get_interface_ip() . ":" . $_GET['nas_port']);
+ "calling_station_id" => $untrusted_ip);
foreach ($authmodes as $authmode) {
$authcfg = auth_get_authserver($authmode);
- ovpn_auth_verify_async.patch
--- /usr/local/sbin/ovpn_auth_verify_async 2024-02-14 01:11:07.610506000 -0800
+++ /usr/local/sbin/ovpn_auth_verify_async.duofix 2024-02-14 02:58:54.461206000 -0800
@@ -62,7 +62,7 @@
# ---------- Perform Check
auth_credentials="username=${username}&password=${password}"
# Note that common_name is also assumed to be set by the environment
-auth_server_1="cn=${common_name}&strictcn=${strictcn}&authcfg=${authcfg}&dev=${dev}&untrusted_port=${untrusted_port}"
+auth_server_1="cn=${common_name}&strictcn=${strictcn}&authcfg=${authcfg}&dev=${dev}&untrusted_port=${untrusted_port}&untrusted_ip=${untrusted_ip}"
auth_server_2="modeid=${modeid}&nas_port=${nas_port}"
auth_args="${auth_credentials}&${auth_server_1}&${auth_server_2}"
Updated by Erich Weiler about 1 month ago
Beautiful, thank you so much! It works like a charm. This is so great. Thanks a million!
Updated by Brandon Verkada about 1 month ago
Erich Weiler wrote in #note-10:
Beautiful, thank you so much! It works like a charm. This is so great. Thanks a million!
Happy to help, solved a lot of issues in our company as well. People are much happier :)
In any case, don't forget to reapply the patch after Netgate pushes a pfSense update (which is rare nowadays) as the files can get overwritten by default versions.