PPP CHAP认证原理与配置详解:三次握手、排错与双向认证

发布时间:2026/10/26 19:16:40
PPP CHAP认证原理与配置详解:三次握手、排错与双向认证

PPP 的 CHAP 认证是网络实验里绕不开的一道坎,很多人第一次在模拟器里配的时候,两边一敲ppp authentication-mode chap,链路直接起不来,然后就开始抓瞎。我自己当年也是这么过来的,明明 PAP 配一次就通,换成 CHAP 就各种报错,后来把报文一个个拆开看才彻底搞明白。这篇内容就围绕PPP 点对点协议中的 CHAP 认证展开,把原理、配置命令、排错思路一次讲透,适合刚接触广域网协议的网络方向学习者、准备实验考试的备考人员,以及需要在模拟环境里复现认证过程的从业者参考。看完你至少能做到三件事:说清楚 CHAP 三次握手的每一步在干什么、独立写出两端认证的完整配置、遇到认证失败时知道从哪几个方向去查。下面全部基于常见模拟器环境下的通用实践来写,命令以主流网络设备厂商的通用语法为准,具体平台可能有细微差异,但思路是通的。

1. 先搞清楚 CHAP 到底在解决什么问题

1.1 PPP 链路建立的四阶段与认证的位置

要理解 CHAP,得先知道它在 PPP 整个流程里站在哪个位置。PPP 链路从物理层起来到能传数据,中间要经过几个明确的阶段,这个顺序不能乱,乱了就通不了。

第一个阶段是链路建立阶段(LCP 协商)。两端通过 LCP 报文协商一堆链路层参数,比如最大接收单元 MRU、认证协议类型、魔术字、是否压缩等等。这里有个关键点:认证协议的选择就是在 LCP 阶段谈定的。也就是说,如果一端要求 CHAP,另一端必须同意,否则 LCP 协商直接失败,链路根本进不了后面的认证阶段。很多人配置完发现链路起不来,其实卡在 LCP 而不是认证本身,这个区分很重要。

第二个阶段是认证阶段。LCP 谈好了用 CHAP,就进入认证环节。注意,认证是可选的,如果两端都没配认证,LCP 协商完直接跳到网络层协商。但只要有一端要求认证,就必须走完这个阶段才能继续。

第三个阶段是网络层协议协商阶段(NCP)。认证通过后,才开始协商 IPCP 之类的网络层参数,分配 IP 地址、协商 DNS 等。这里能看出一个设计逻辑:认证是网络层通信的前置门槛,没过认证,IP 层的东西一概不谈。

第四个阶段是链路终止阶段,链路要拆的时候通过 LCP 报文终止。

把这四个阶段串起来看,CHAP 的位置就很清晰了:它夹在 LCP 和 NCP 之间,是一道"门禁"。门禁没通过,后面的网络层协商一步都走不了。理解这个层次关系,排错时你就知道该看哪一层的日志——如果 LCP 都没起来,别去查 CHAP 配置;如果 LCP 起来了但认证失败,那才是 CHAP 的问题。

1.2 PAP 和 CHAP 的本质区别在哪

既然讲 CHAP,就绕不开和 PAP 的对比,因为很多人是先学了 PAP 再学 CHAP,容易把两者的行为搞混。我用一句话概括:PAP 是明文报口令,CHAP 是不传口令只传摘要。

PAP 的过程特别简单,就是两次握手:被认证方直接把用户名和密码明文发给认证方,认证方比对数据库,对就通过,错就拒绝。整个过程密码在链路上是裸奔的,抓个包就能看到,安全性很差。而且 PAP 只在链路建立时认证一次,之后就不再管了,属于"进门查一次票,进去随便逛"。

CHAP 完全不一样,它是三次握手,而且核心是不传密码本身。认证方发一个随机挑战值(Challenge),被认证方用这个挑战值加上自己的密码,经过 MD5 哈希算出一个摘要(Response)发回去,认证方自己也算一遍,两边对得上就通过。密码从头到尾没在链路上出现过,抓包也只能看到一个哈希值,而且每次挑战值不同,算出来的摘要也不同,重放攻击基本没戏。

还有一个容易被忽略的差异:CHAP 支持周期性重认证。链路建立后,认证方可以隔一段时间再发一次挑战,重新验证对方身份,防止链路被中途劫持。PAP 没有这个机制。这个特性在实际配置里对应一个chap ...相关的定时参数,后面会讲到。

对比维度PAPCHAP
握手次数两次三次
密码传输明文不传密码,只传 MD5 摘要
安全性低,可被抓包较高,抗重放
重认证不支持支持周期性重认证
认证方向单向为主可单向可双向
配置复杂度简单稍复杂,需注意用户名匹配

这张表建议记牢,考试和实际排错都用得上。尤其是"认证方向"这一行,CHAP 的双向认证是很多实验题的考点,也是配置最容易出错的地方。

1.3 CHAP 三次握手的报文级拆解

光说"三次握手"太抽象,我把每一步的报文交互拆开讲,你对着抓包就能一一对应上。

第一步:Challenge(挑战)。认证方(Authenticator)生成一个随机数,加上自己的主机名标识,封装成 Challenge 报文发给被认证方。这个随机数的长度一般是 16 字节,每次认证都重新生成,这是抗重放的关键。报文里还带一个 ID 字段,用来匹配后续的响应,因为可能同时有多个认证在进行。

第二步:Response(响应)。被认证方收到 Challenge 后,取出随机数,找到本地存储的对应"认证方用户名"的密码,把ID + 随机数 + 密码三样东西拼在一起做 MD5 运算,得到一个 16 字节的摘要。然后把自己的用户名 + 这个摘要封装成 Response 报文发回去。注意,这里发的是自己的用户名,不是密码,认证方靠这个用户名去自己的数据库里找对应的密码来验算。

第三步:Success 或 Failure(成功/失败)。认证方收到 Response,用报文里的用户名查本地配置的密码,同样把 ID + 随机数 + 密码做 MD5,和自己收到的摘要比对。一致就回 Success,链路进入 NCP 阶段;不一致就回 Failure,链路直接终止,而且通常会等一段时间再重试。

这里有个特别容易踩的坑:被认证方做 MD5 用的密码,是"认证方用户名对应的密码",不是自己的用户名对应的密码。换句话说,A 认证 B 的时候,B 要用"A 的用户名"去查密码来做摘要。这个逻辑第一次接触的人几乎都会绕晕,配置时用户名对不上就是认证失败的头号原因。我后面在配置章节会专门用例子把这个对应关系讲清楚。

2. 配置前的准备工作与关键参数

2.1 实验拓扑与地址规划

配置之前先把环境搭好,我这里用一个最经典的两点直连拓扑来说明,这种拓扑在模拟器里搭起来最快,也最能说明问题。两台路由器通过串口(Serial)直连,模拟广域网链路。为什么用串口而不是以太网口?因为 PPP 本质是广域网协议,串口是它最典型的载体,虽然现在以太网上也能跑 PPPoE,但学原理阶段用串口最纯粹。

地址规划上,串口链路我习惯用一个独立的网段,比如10.1.1.0/30,两端分别是10.1.1.1和10.1.1.2。用 /30 是因为点对点链路只需要两个可用地址,/30 正好两个,不浪费。如果你习惯用 /24 也无所谓,实验环境不讲究这个,但养成节约地址的习惯没坏处。

设备命名上,我把认证方叫 R1,被认证方叫 R2。这个角色划分很重要,因为 CHAP 的配置是不对称的——认证方要配"对谁做认证、用什么方式",被认证方要配"给对方什么用户名密码"。角色搞反了,命令就全配错了。

提示:模拟器里串口默认可能是 shutdown 状态,配地址前先undo shutdown,否则接口起不来,你会误以为是 PPP 的问题。这个坑我踩过不止一次。

2.2 用户名和密码的对应关系设计

这是 CHAP 配置里最烧脑的部分,我单独拎出来讲。CHAP 认证涉及两个方向的"用户名密码"概念,必须分清楚:

  • 本地用户名密码:本设备上配置的local-user xxx password ...,这是"我用来验证别人"或者"别人用来验证我"的凭据。
  • 对端用户名:在接口上通过ppp chap user xxx指定的,告诉对方"我是谁"。

关键规则是:认证方验证被认证方时,用的是认证方本地数据库里"被认证方用户名"对应的密码;被认证方计算摘要时,用的是自己本地数据库里"认证方用户名"对应的密码。

我用具体例子说明。假设 R1 认证 R2,约定:

  • R2 用自己的用户名r2user向 R1 表明身份;
  • R1 本地要有一条r2user的记录,密码设为r2pass;
  • R2 本地要有一条r1user的记录(R1 的用户名),密码也设为r2pass。

看出来了吗?两边的密码必须一致,但用户名各配各的。R1 存的是"R2 的用户名 + 密码",R2 存的是"R1 的用户名 + 密码",而这两个密码值是同一个。这就是 CHAP 最容易配错的地方——很多人两边密码配成不一样的,或者用户名对不上,认证必然失败。

为了让你更直观,我把这个对应关系做成表:

设备角色本地需配置的用户密码接口上指定的 chap user
R1认证方r2userr2pass可不配(认证方主动发挑战)
R2被认证方r1userr2passr2user

注意最后一行,R2 接口上要配ppp chap user r2user,意思是"我向对方报的用户名是 r2user"。而 R1 本地存的正是r2user这个用户,密码r2pass。R2 本地存的r1user是给"如果 R1 也反过来认证 R2"或者双向认证时用的。单向认证场景下,R2 本地那条r1user其实在计算摘要时用不到——等等,这里要纠正一个常见误解。

实际上,被认证方计算 Response 摘要时,用的密码是"认证方用户名对应的密码"。也就是说 R2 收到 R1 的 Challenge(里面带 R1 的主机名),R2 要去本地找"R1 的用户名"对应的密码来做 MD5。所以 R2 本地必须配r1user且密码为r2pass,否则 R2 根本算不出正确的摘要。这就是为什么上表里 R2 要配r1user。这个细节很多教程讲得含糊,我当年就是卡在这里,配了半天发现 R2 本地没配 R1 的用户,摘要算出来对不上。

2.3 认证方式的选择:单向还是双向

CHAP 支持单向认证和双向认证,选哪个取决于你的安全需求。

单向认证:只有一端认证另一端,比如 R1 认证 R2,R2 不认证 R1。配置简单,适合"中心节点验证接入节点"的场景,比如总部验证分支机构。

双向认证:两端互相认证,R1 认证 R2 的同时 R2 也认证 R1。安全性更高,但配置量翻倍,两边都要配本地用户和接口认证。实际项目里,如果两端地位对等、都需要确认对方身份,就用双向。

实验阶段我建议先配单向跑通,再改双向。因为单向的变量少,出问题好定位;一上来就配双向,失败了都不知道是哪个方向的问题。这个循序渐进的方法是我调试任何认证类配置的通用套路。

3. 完整配置命令逐条拆解

3.1 认证方 R1 的配置

先配认证方。R1 要做的事:开启 CHAP 认证、在本地建好被认证方的用户、在接口上启用 CHAP 认证。

第一步,进系统视图配本地用户。命令是local-user r2user password cipher r2pass,然后local-user r2user service-type ppp。这里service-type ppp不能漏,它限定这个用户只能用于 PPP 认证,是个安全约束。密码用cipher表示密文存储,比simple明文存储安全,虽然实验环境无所谓,但养成习惯。

第二步,进串口接口视图,配ppp authentication-mode chap。这条命令的意思是"本接口用 CHAP 方式认证对端"。注意,这条命令是认证方才配的,被认证方不配这条(或者说配了就是要求认证对方,角色就变了)。

第三步,可选地配ppp chap hostname r1user,指定本端在 CHAP 交互中报的主机名。如果不配,默认用设备的主机名。单向认证场景下这条可以不配,但双向认证时必须配,因为对方要靠这个名字查密码。

R1 的完整配置大概长这样:

system-view sysname R1 local-user r2user password cipher r2pass local-user r2user service-type ppp interface Serial1/0/0 ip address 10.1.1.1 255.255.255.252 ppp authentication-mode chap ppp chap hostname r1user undo shutdown

逐条解释一下为什么这么配。local-user两条是给认证方准备"验证别人的凭据",ppp authentication-mode chap是声明"我要认证你",ppp chap hostname是告诉对方"我叫 r1user",方便对方查密码。地址配 /30 前面说过了。undo shutdown是激活接口。

注意:ppp authentication-mode chap配在接口上后,接口会立即开始要求对端认证。如果对端还没配好,链路会一直卡在认证阶段,日志里能看到 CHAP 认证失败的记录。这是正常现象,别慌。

3.2 被认证方 R2 的配置

R2 要做的事:配好认证方的用户(用于算摘要)、在接口上声明自己报的用户名。

第一步,同样配本地用户,但这次配的是认证方 R1 的用户名:local-user r1user password cipher r2pass,local-user r1user service-type ppp。密码还是r2pass,和 R1 那边保持一致。

第二步,进接口配ppp chap user r2user,意思是"我向对方报的用户名是 r2user"。这条命令对应 R1 本地存的r2user用户,两边就对上了。

第三步,配地址10.1.1.2 255.255.255.252,undo shutdown。

R2 的完整配置:

system-view sysname R2 local-user r1user password cipher r2pass local-user r1user service-type ppp interface Serial1/0/0 ip address 10.1.1.2 255.255.255.252 ppp chap user r2user undo shutdown

对比 R1 和 R2 的配置,你会发现一个有意思的对称性:R1 配authentication-mode chap但没配chap user(单向场景),R2 配chap user但没配authentication-mode。这就是单向认证的典型形态——一方要求认证,一方表明身份。

如果你要配双向认证,那就把两边的配置合并:R1 也加上ppp chap user r1user,R2 也加上ppp authentication-mode chap,同时两边本地用户都要配齐(R1 配 r2user,R2 配 r1user,密码一致)。这样两端互相认证,任何一方验证失败链路都起不来。

3.3 验证配置是否生效

配完不能光看接口 up 了就完事,得确认认证真的过了。几个验证手段:

第一,display interface Serial1/0/0看接口的 Line protocol 状态。如果显示 up,说明 LCP 和认证都过了;如果显示 down 或 spoofing,说明卡在某一层。

第二,display ppp interface Serial1/0/0看 PPP 的详细状态,能看到 LCP 是否 open、认证是否成功、NCP 是否协商完成。这个命令信息量大,排错时必看。

第三,开调试。debugging ppp chap all能看到 CHAP 报文的交互过程,Challenge、Response、Success 每一步都有打印。调试完记得undo debugging all关掉,否则日志刷屏影响性能。这个手段最直接,认证失败时能看到具体是哪一步出的问题。

第四,ping对端地址。能 ping 通说明整条链路(物理层、PPP、IP 层)全通了,这是最终的验收标准。

我一般的验证顺序是:先看接口状态,再看 PPP 详细状态,不通就开 debug,最后 ping 验收。这个顺序从粗到细,效率最高。

4. 认证失败的排查思路与常见坑

4.1 从日志和调试信息定位问题

CHAP 认证失败,日志里通常会有明确的提示,关键是会看。常见的几类报错:

  • CHAP authentication failed:最笼统的失败,说明摘要对不上,往下查用户名密码。
  • LCP negotiation failed:这其实不是 CHAP 的问题,是 LCP 阶段就没谈拢,可能一端要求 CHAP 另一端不支持,或者 MRU 之类的参数不匹配。
  • No response received:被认证方没回 Response,可能是被认证方没配chap user,或者链路物理层有问题。

开debugging ppp chap all后,正常流程的打印大概是:发 Challenge、收 Response、验证通过发 Success。如果卡在发 Challenge 后没收到 Response,问题在被认证方;如果收到 Response 但验证失败,问题在密码或用户名匹配。

我排错时有个习惯:先确认 LCP 起来了没有。因为如果 LCP 都没起来,CHAP 的调试信息根本不会出现,你查半天 CHAP 配置是白费功夫。用display ppp interface看 LCP 状态,open 了才往下查认证。

4.2 用户名密码不匹配的典型场景

这是最高频的失败原因,我列几个具体的坑:

坑一:两边密码不一致。前面强调过,认证方本地存的"被认证方用户名"的密码,和被认证方本地存的"认证方用户名"的密码,必须是同一个值。有人配的时候 R1 存 r2user 密码 123,R2 存 r1user 密码 456,摘要当然对不上。

坑二:chap user和本地用户名对不上。R2 接口上配ppp chap user r2user,但 R1 本地配的用户是r2,名字差一点,R1 收到 Response 后拿r2user去查数据库查不到,直接失败。

坑三:忘了配service-type ppp。本地用户配了密码但没指定服务类型,PPP 认证时这个用户不可用,等于没配。这个错误很隐蔽,因为用户确实存在,但就是认证不过。

坑四:被认证方本地没配认证方的用户。前面讲过,被认证方算摘要要用"认证方用户名对应的密码",如果 R2 本地没配r1user,它收到 Challenge 后找不到密码,算不出正确摘要。这个是最容易忽略的,因为直觉上会觉得"我被认证,配我自己的密码就行了",但 CHAP 的逻辑不是这样。

4.3 一个高频问题速查表

我把实际调试中遇到的典型现象和对应原因整理成表,出问题时对着查,能省不少时间:

现象可能原因排查动作
接口 Line protocol downLCP 未协商成功查两端 LCP 参数、认证方式是否一致
日志报 CHAP authentication failed密码不一致或用户名不匹配核对两端本地用户和 chap user
发 Challenge 后无响应被认证方未配 chap user 或链路断查被认证方接口配置和物理链路
认证通过但 ping 不通NCP 未协商或地址配错查 IP 地址、IPCP 状态
周期性掉线重认证重认证定时器触发且凭据失效查密码是否被改、重认证间隔
双向认证只有一向通过某一方向本地用户缺失两端都检查本地用户配置

这张表里"周期性掉线重认证"这一行值得多说一句。CHAP 支持重认证,如果配了较短的间隔,链路会定期重新验证。如果这期间密码被改了或者用户被删了,链路就会周期性断开。实际项目里如果遇到"链路每隔一段时间断一次又自动恢复",先怀疑重认证相关的配置。

4.4 实操心得:调试顺序比命令更重要

分享一个我调试认证类问题的固定套路,屡试不爽:

第一步,物理层先确认。接口物理状态 up 了吗?display interface看 Physical 是不是 up。物理层不通,上面全是空谈。

第二步,LCP 层确认。display ppp interface看 LCP 状态。LCP 不通,查认证方式是否两端匹配、MRU 等参数。

第三步,认证层确认。开 debug 看 CHAP 交互,定位是没响应还是验证失败。

第四步,网络层确认。认证过了 ping 不通,查 IP 地址和 NCP 协商。

这个从下往上的顺序,本质上是按 PPP 的协议栈层次来查,每一层确认没问题再往上走。很多人一上来就盯着 CHAP 配置看,结果发现是物理层接口没undo shutdown,白折腾半天。层次化排查是网络排错的基本功,比记住多少条命令都重要。

5. 进阶:双向认证与安全加固

5.1 双向认证的配置要点

双向认证在实际项目里用得不少,尤其是两端都需要确认对方身份的场景。配置上就是把单向的两套配置合并,但有几个细节要注意。

R1 的配置在单向基础上增加:接口加ppp chap user r1user(声明自己报的用户名),本地用户除了r2user还要确保有r1user吗?不需要,R1 认证 R2 用r2user,R2 认证 R1 时 R1 报r1user,R2 本地要有r1user。R1 本地只需要r2user(用于认证 R2)。等等,这里又要理清:双向认证时,R1 既认证 R2 又被 R2 认证。R1 认证 R2 用本地r2user;R1 被 R2 认证时,R1 报r1user,R2 本地要有r1user且密码一致。所以 R1 本地配r2user,R2 本地配r1user,密码都是r2pass(或者你约定的统一密码)。R1 接口配authentication-mode chap和chap user r1user,R2 接口配authentication-mode chap和chap user r2user。

我把双向认证的完整配置列一下,方便对照:

# R1 双向认证配置 system-view sysname R1 local-user r2user password cipher r2pass local-user r2user service-type ppp interface Serial1/0/0 ip address 10.1.1.1 255.255.255.252 ppp authentication-mode chap ppp chap user r1user undo shutdown # R2 双向认证配置 system-view sysname R2 local-user r1user password cipher r2pass local-user r1user service-type ppp interface Serial1/0/0 ip address 10.1.1.2 255.255.255.252 ppp authentication-mode chap ppp chap user r2user undo shutdown

对比单向配置,双向就是两边都加了authentication-mode chap和chap user。看起来简单,但用户名密码的对应关系一定要按前面讲的规则来,否则两个方向总有一个过不了。

5.2 重认证定时器与安全参数

CHAP 的重认证能力是它比 PAP 强的重要一点。认证方可以配置重认证的间隔,定期重新验证对端身份。相关命令通常是ppp chap ...系列里的定时参数,具体语法各平台略有差异,常见的是在接口下配重认证时间。

配重认证的考量:间隔太短,频繁认证增加开销,链路可能因为瞬时问题误断;间隔太长,安全性下降,链路被劫持后长时间发现不了。实际项目里一般设几分钟到几十分钟,实验环境可以不配或者设长一点,避免调试时被重认证干扰。

除了重认证,还有几个安全加固点值得注意。一是密码强度,虽然实验环境随便设,但实际项目里密码要够复杂,因为 CHAP 的摘要虽然不直接暴露密码,但如果密码太弱,理论上存在被暴力破解的风险。二是本地用户的service-type要严格限定为 ppp,避免这个账号被用于其他服务。三是定期更换密码,配合重认证机制,能及时发现凭据失效。

5.3 CHAP 与 PAP 的混合使用场景

有时候会遇到一端要求 CHAP、另一端只支持 PAP 的情况,或者为了兼容老设备需要降级。PPP 允许在 LCP 阶段协商认证协议,如果一端配了ppp authentication-mode chap pap,意思是"优先 CHAP,对端不支持就退到 PAP"。这种配置在兼容性场景下有用,但安全性打了折扣,因为一旦退到 PAP,密码就明文传输了。

我的建议是:能 CHAP 就 CHAP,不要为了省事配 pap 回退。如果确实要兼容,至少确认链路环境是可信的,比如专线直连,不经过不可控的中间网络。实验环境里可以试试这个回退配置,观察 LCP 协商时认证协议是怎么谈的,对理解 PPP 的协商机制很有帮助。

6. 从实验到实战:几个值得记住的经验

6.1 模拟器与真实设备的差异

模拟器里配通了,不代表真实设备上一定没问题,有几个差异点要心里有数。模拟器对某些命令的支持可能不完整,比如重认证定时器的具体参数,模拟器可能不生效或者默认值不同。另外模拟器的串口是虚拟的,物理层不会真的出问题,所以物理层排错的经验在模拟器里练不到,真实环境里线缆、接口、时钟频率这些都可能成为故障点。

还有一个差异是性能。模拟器上开 debug 随便开,真实设备上 debug 输出过多会占用 CPU,可能影响转发甚至导致链路抖动。所以真实环境开 debug 要谨慎,最好在业务低峰期,并且配好 ACL 限制调试范围,调完立刻关。

6.2 认证配置的复用与模板化

如果项目里有多条 PPP 链路要配 CHAP,别一条条手敲,容易出错还慢。我的做法是整理一个配置模板,把用户名密码、接口地址这些变量抽出来,用脚本批量生成。模板的核心就是前面讲的那套对应关系:认证方配authentication-mode和本地被认证方用户,被认证方配chap user和本地认证方用户,密码统一。

模板化还有个好处是一致性。手工配多条链路,很容易某条链路的密码敲错一个字符,排查起来极其痛苦。用模板生成,至少保证结构一致,出问题也好对比。这个习惯在规模稍大的网络里特别值钱。

6.3 排错时最该先看的三样东西

最后分享我个人的排错优先级,遇到 PPP CHAP 问题,我按这个顺序看:

第一看接口物理状态和协议状态,display interface一条命令就能看出物理层和链路层的大致情况。第二看PPP 详细状态,display ppp interface能定位到 LCP、认证、NCP 哪一层卡住。第三看调试信息,前两步定位到认证层后,开debugging ppp chap all看具体报文交互。

这三样看完,90% 的问题都能定位。剩下 10% 是比较刁钻的,比如用户名大小写敏感、特殊字符转义、密码里带了空格之类的,这些只能靠仔细核对配置。我遇到过密码末尾多敲一个空格的,debug 看摘要就是不对,查了半天才发现是空格问题,这种坑只能靠细心。

CHAP 这套机制设计得其实很优雅,用摘要代替明文、用随机挑战抗重放、用重认证防劫持,每一步都有明确的安全考量。把三次握手的报文交互和用户名密码的对应关系吃透,配置就是照葫芦画瓢的事。真正花时间的从来不是敲命令,而是理解"为什么这么配"——这也是我在带新人时反复强调的一点,命令可以查文档,但对应关系搞不清,出了问题就只能干瞪眼。