共享秘钥模式下XAUTH验证流程

2023-11-27 22:40

本文主要是介绍共享秘钥模式下XAUTH验证流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以下根据strongswan代码中的testing/tests/ikev1/xauth-psk/中的测试环境,来看一下XAUTH验证流程。拓扑结构如下:

在这里插入图片描述

拓扑图中使用到的设备包括:虚拟网关moon和主机carol及dave。

moon网关配置

moon的配置文件:/etc/ipsec.conf,内容如下。注意此处keyexchange字段的值,使用ikev1版本协议。在名称为rw的连接配置中,leftauth和rightauth字段都指定了psk共享秘钥认证,另外rightauth2的值xauth,表明执行第二级的XAUTH认证。

conn %defaultkeyexchange=ikev1conn rwleft=PH_IP_MOONleftid=@moon.strongswan.orgleftsubnet=10.1.0.0/16leftauth=pskleftfirewall=yesright=%anyrightauth=pskrightauth2=xauth

PSK模式和XAUTH认证的秘钥信息保存在文件/etc/ipsec.secrets中,内容如下。对于ID值为carol@strongswan.org和dave@strongswan.org的连接使用不同的XAUTH秘钥。

moon.strongswan.org %any : PSK 0sv+NkxY9LLZvwj4qCC2o/gGrWDF2d21jLcarol@strongswan.org : XAUTH "4iChxLT3"dave@strongswan.org  : XAUTH "ryftzG4A"

配置文件/etc/strongswan.conf中的插件xauth-generic负责处理XAUTH相关认证工作。其相关代码位于目录:strongswan-5.8.1/src/libcharon/plugins/xauth_generic/。

charon {load = random nonce aes sha1 sha2 hmac curve25519 xauth-generic kernel-netlink socket-default updown stroke
}

主机配置

carol主机的配置文件:/etc/ipsec.conf,内容如下。其中与网关moon使用相同的ikev1版本协议以及共享秘钥psk认证。此外,leftauth2的值xauth表明本机将进行第二级的XAUTH认证。

conn %defaultkeyexchange=ikev1conn homeleft=PH_IP_CAROLleftid=carol@strongswan.orgleftauth=pskleftauth2=xauthleftfirewall=yesright=PH_IP_MOONrightsubnet=10.1.0.0/16rightid=@moon.strongswan.orgrightauth=pskauto=add

PSK秘钥和XAUTH秘钥保存在carol主机文件/etc/ipsec.secrets中,如下所示。可见其与moon网关的/etc/ipsec.secrets文件中指定的秘钥相同,否则无法完成认证。

: PSK 0sv+NkxY9LLZvwj4qCC2o/gGrWDF2d21jLcarol@strongswan.org : XAUTH "4iChxLT3" 

此外,carol主机的strongswan.conf文件中同样加载了xauth-generic插件。dave主机的配置与carol基本系统,区别在于一些主机相关选项和XAUTH秘钥的差别。

连接建立流程

分别在三台机器上启动strongswan进程,以及在carol和dave主机上启动home连接。

moon::ipsec start
carol::ipsec start
dave::ipsec start
moon::expect-connection rw
carol::expect-connection home
carol::ipsec up home
dave::expect-connection home
dave::ipsec up home

在ikev1的主模式第一报文中,carol主机通告了对XAUTH的支持,如下报文,

在这里插入图片描述

接下来在回复报文中,moon网关同样通告了对XAUTH的支持,如下。

在这里插入图片描述

之后XAUTH认证在第一阶段Main模式和第二阶段Quick模式之间开始进行,其增加了4个Config配置模式的报文来完成XAUTH认证。

在这里插入图片描述

第一个报文由moon网关发到carol的请求报文,类型为:ISAKMP_CFG_REQUEST(1),其请求两个属性:XAUTH_USER_NAME(16521)和XAUTH_USER_PASSWORD(16522)。

在这里插入图片描述

第二个报文为carol的回复报文,类型为:ISAKMP_CFG_REPLY(2),其在属性XAUTH_USER_NAME和XAUTH_USER_PASSWORD中分别携带自身的用户名(carol@strongswan.org)和秘钥(4iChxLT3)。此与moon网关配置的秘钥相同。
在这里插入图片描述

第三个报文为moon网关发送的验证结果报文,类型为:ISAKMP_CFG_SET(3),其中属性XAUTH_STATUS表明,此次认证成功(值为1)。

在这里插入图片描述

最好一个报文为carol对验证结果的确认,类型为:ISAKMP_CFG_ACK(4),其中属性XAUTH_STATUS带有长度为0的值(无值)。

在这里插入图片描述

状态信息

使用ip命令在moon和sun网关上查看创建的GRE隧道设备,ikey和okey两个方向的值都为42。

moon:~# ip -d link show gre-moon
24: gre-moon@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1472 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/gre 192.168.0.1 peer 192.168.0.2 promiscuity 0 gre remote 192.168.0.2 local 192.168.0.1 ttl inherit ikey 0.0.0.42 okey 0.0.0.42 addrgenmode eui64 numtxqueues 1 gso_max_size 65536 gso_max_segs 65535 
moon:~#sun:~# ip -d link show gre-sun
26: gre-sun@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1472 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/gre 192.168.0.2 peer 192.168.0.1 promiscuity 0 gre remote 192.168.0.1 local 192.168.0.2 ttl inherit ikey 0.0.0.42 okey 0.0.0.42 addrgenmode eui64 numtxqueues 1 gso_max_size 65536 gso_max_segs 65535 
sun:~# 

使用ip route命令查看为gre-moon虚拟接口添加的路由信息,目的网段10.2.0.0/16(bob主机所在网段)的流量路由到gre-moon接口。

moon:~# ip route
default via 192.168.0.254 dev eth0 onlink 
10.1.0.0/16 dev eth1 proto kernel scope link src 10.1.0.1 
10.2.0.0/16 dev gre-moon scope link 
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.1 
moon:~# 

XAUTH通用插件

文件:strongswan-5.8.1/src/libcharon/plugins/xauth_generic/xauth_generic.c为此处使用的xauth_generic插件的实现代码。函数xauth_generic_create_server将创建一个xauth认证服务器,

xauth_generic_t *xauth_generic_create_server(identification_t *server, identification_t *peer, char *profile)
{       private_xauth_generic_t *this;INIT(this,.public = {.xauth_method = { .initiate = _initiate_server,.process = _process_server,.get_identity = _get_identity,.destroy = _destroy,},},.server = server->clone(server),.peer = peer->clone(peer),);

初始化函数initiate_server如下,其将创建类型为CFG_REQUEST的报文(对应以上的ISAKMP_CFG_REQUEST报文),并且添加两个配置属性XAUTH_USER_NAME和XAUTH_USER_PASSWORD,但是这两个数据的值都为空(chunk_empty)。此即以上提到的moon网关发送的第一个XAUTH报文。

METHOD(xauth_method_t, initiate_server, status_t, private_xauth_generic_t *this, cp_payload_t **out)
{cp_payload_t *cp;cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);cp->add_attribute(cp, configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));cp->add_attribute(cp, configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));*out = cp;return NEED_MORE;
}

函数process_server负责由认证客户端的回复消息中获取用户名和秘钥属性值,并与服务端的用户秘钥进行对比,验证是否相等。

METHOD(xauth_method_t, process_server, status_t, private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
{enumerator = in->create_attribute_enumerator(in);while (enumerator->enumerate(enumerator, &attr)){switch (attr->get_type(attr)){case XAUTH_USER_NAME:user = attr->get_chunk(attr);break;case XAUTH_USER_PASSWORD:pass = attr->get_chunk(attr);while (enumerator->enumerate(enumerator, &shared, NULL, NULL)){if (chunk_equals_const(shared->get_key(shared), pass)){status = SUCCESS;

以下函数xauth_generic_create_peer用于创建一个认证客户端结构。与以上的服务端不同,此处的initiate_peer函数为空,客户端不需要进行初始化。

xauth_generic_t *xauth_generic_create_peer(identification_t *server, identification_t *peer, char *profile)
{private_xauth_generic_t *this;INIT(this,.public =  {.xauth_method = {.initiate = _initiate_peer,.process = _process_peer,.get_identity = _get_identity,.destroy = _destroy,},},.server = server->clone(server),.peer = peer->clone(peer),

客户端处理函数process_peer负责处理服务器的认证消息,这里创建CFG_REPLY类型的回复消息,增加XAUTH_USER_NAME和XAUTH_USER_PASSWORD两个属性字段,并且赋予相应的值。

METHOD(xauth_method_t, process_peer, status_t, private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
{cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);enumerator = in->create_attribute_enumerator(in);while (enumerator->enumerate(enumerator, &attr)){switch (attr->get_type(attr)){case XAUTH_USER_NAME:cp->add_attribute(cp, configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME,this->peer->get_encoding(this->peer)));break;case XAUTH_USER_PASSWORD:shared = lib->credmgr->get_shared(lib->credmgr, type, this->peer, this->server);cp->add_attribute(cp, configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE, attr->get_type(attr),shared->get_key(shared)));

XAUTH任务

XAUTH任务处理代码位于:strongswan-5.8.1/src/libcharon/sa/ikev1/tasks/xauth.c文件中,与以上的xauth插件类似,函数xauth_create首先创建一个private_xauth_t结构,并根据第二个参数initiator的值,创建initiator或者responder任务。

xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
{private_xauth_t *this;INIT(this,.initiator = initiator,.ike_sa = ike_sa,.status = XAUTH_FAILED,);if (initiator) {this->public.task.build = _build_i;this->public.task.process = _process_i;} else {this->public.task.build = _build_r;this->public.task.process = _process_r;

函数build_i_status负责创建XAUTH的认证结果报文,类型为CFG_SET,增加属性XAUTH_STATUS。

METHOD(task_t, build_i_status, status_t, private_xauth_t *this, message_t *message)
{cp_payload_t *cp;cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);cp->add_attribute(cp,configuration_attribute_create_value(XAUTH_STATUS, this->status));message->add_payload(message, (payload_t *)cp);

函数build_r_ack负责创建XAUTH的认证结果却认报文(即XAUTH的第四个报文),类型为CFG_ACK,属性XAUTH_STATUS的值为空(chunk_empty)。

METHOD(task_t, build_r_ack, status_t, private_xauth_t *this, message_t *message)
{cp_payload_t *cp;cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);cp->set_identifier(cp, this->identifier);cp->add_attribute(cp,configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_STATUS, chunk_empty));message->add_payload(message, (payload_t *)cp);

以下build_i函数,如果当前xauth结构没有关联认证方法,使用load_method进行关联,即上一节介绍的xauth_generic通用方法。之后调用方法的initiate函数,对于认证服务器的角色,initiate函数为:initiate_server函数;但是对于认证客户端而言,其initiate函数initiate_peer实际上为空,参见以上的介绍。前者initiate_server函数返回值为NEED_MORE。

METHOD(task_t, build_i, status_t, private_xauth_t *this, message_t *message)
{if (!this->xauth){cp_payload_t *cp = NULL;this->xauth = load_method(this);if (!this->xauth) {return FAILED;}switch (this->xauth->initiate(this->xauth, &cp)){case NEED_MORE:break;case SUCCESS:DESTROY_IF(cp);if (add_auth_cfg(this, NULL, FALSE) && allowed(this)) {this->status = XAUTH_OK;}this->public.task.process = _process_i_status;return build_i_status(this, message);default:return FAILED;}message->add_payload(message, (payload_t *)cp);return NEED_MORE;

函数process_r为认证客户端的处理服务器报文所使用。根据认证服务器的报文类型CFG_REQUEST或者CFG_SET进行不同的处理。对于CFG_REQUEST报文,需要调用xauth_generic插件的process函数指针进行处理,即函数process_peer。最后启动build任务,即build_r_ack函数创建回复报文。

METHOD(task_t, process_r, status_t, private_xauth_t *this, message_t *message)
{if (cp->get_type(cp) == CFG_REQUEST) {switch (this->xauth->process(this->xauth, cp, &this->cp)) {case NEED_MORE:return NEED_MORE;case SUCCESS:case FAILED:default:break;}this->cp = NULL;return NEED_MORE;}if (cp->get_type(cp) == CFG_SET) {configuration_attribute_t *attribute;enumerator_t *enumerator;enumerator = cp->create_attribute_enumerator(cp);while (enumerator->enumerate(enumerator, &attribute)) {if (attribute->get_type(attribute) == XAUTH_STATUS) {this->status = attribute->get_value(attribute);}}enumerator->destroy(enumerator);if (this->status == XAUTH_OK && add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE)) {DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful", this->xauth->get_identity(this->xauth));} else {DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed", this->xauth->get_identity(this->xauth));}}this->identifier = cp->get_identifier(cp);this->public.task.build = _build_r_ack;

strongswan版本: 5.8.1
内核版本: 5.0

END

这篇关于共享秘钥模式下XAUTH验证流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/428574

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

easyui同时验证账户格式和ajax是否存在

accountName: {validator: function (value, param) {if (!/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/i.test(value)) {$.fn.validatebox.defaults.rules.accountName.message = '账户名称不合法(字母开头,允许4-16字节,允许字母数字下划线)';return fal

easyui 验证下拉菜单select

validatebox.js中添加以下方法: selectRequired: {validator: function (value) {if (value == "" || value.indexOf('请选择') >= 0 || value.indexOf('全部') >= 0) {return false;}else {return true;}},message: '该下拉框为必选项'}

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序