本文主要是介绍共享秘钥模式下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验证流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!