当前位置: 首页 > news >正文

邮件安全之发件人伪造

电子邮件工作原理

  电子邮件传输过程中主要涉及到SMTP、IMAP、POP3三种协议,具体功能如下:

SMTP:全称Simple Mail Transfer Protocol,即简单邮件传输协议,主要用于发送邮件,使用端口号25

IMAP:全称Internet Mail Access Protocol,即交互式邮件存取协议,主要用于收取邮件,使用端口143

POP3:全称Post Office Protocol-Version 3,即邮局协议,主要用于收取邮件,使用端口110

  电子邮件工作的整个过程如下图所示:

image

POP3与IMAP协议:

  POP3和IMAP功能类似,主要用于收件方查看、管理收到的邮件,但是POP3协议具有只能从服务器端将用户的邮件下载到本地进行管理,并且同时会删除服务器端的邮件,而IMAP则可以不对全部邮件下载,直接在服务器上进行查看和其他操作。

SMTP发件过程

工作机制

  SMTP通常有两种工作模式。发送SMTP和接收SMTP。具体工作方式为:发送SMTP在接收到用户的邮件请求后,判断此邮件是否为本地邮件,若直接投送到用户的邮箱否则向DNS查询远端邮件服务器的MX记录,并建立与远端接收SMTP之间的一个双向传送通道,此后SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方向传送。一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此反复多次。当接收者收到全部邮件后会接收到特别的序列,接收者成功处理了邮件,则返回OK应答。

注意:SMTP发送只负责将邮件发送到目标服务器上,而不是直接投递给接受者的邮箱,接受者是通过使用其身份登录到服务器上才仅进行的邮件操作。

服务器查找

  在接收到用户的邮件请求后,如果判断不是本地邮件,则要进行请求邮件发送方的邮件服务器查找,查找过程如下:

  • 查找邮箱后缀域名的MX记录所指向的域名地址
  • 根据指向域名地址通过dns查找域名地址指向的服务器ip
  • tcp连接服务器ip:25(默认端口)(用来登陆或者发送)

  完成服务器查找后直接进行后续的登录发送操作即可。

交互过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> telnet smtp.163.com 25【tcp连接】
220 163.com Anti-spam GT for Coremail System (163com[20141201])【欢迎信息】
>>> HELO 163.com
250 OK
>>> auth login【请求登陆】
334 dXNlcm5dhbWU6【要求用户名】
>>> Z3dfdsaffEDF=【输入base64用户名】
334 UGFzc3ddvcmQ6【要求密码】
>>> fdasDSDFFFfDS=【输入base64密码】
235 Authentication successful【登陆成功】
>>> MAIL FROM:xxx@163.com【发件地址】
rcpt to:xxx@163.com【收件地址】
>>> DATA【data命令,要求发送内容】
354 End data with .【提示信息,以.作为结束符号】
>>> FROM:gule11@163.com【要显示的发件地址】
>>> TO:xxx@163.com【要显示的收件地址】
>>> helllo world【内容】
>>> .【结束】
250 Mail OK queued as smtp13,EcCowABHIv39riFXqUpKBA—.47592S3 1461825582【返回发送状态,我的测试不幸进入垃圾邮件】
>>> QUIT【退出命令】
221 Bye
SMTP常见命令

SMTP命令不区分大小写,但参数区分大小写。常用命令如下:

  • HELO ——向服务器标识用户身份发送者能欺骗、说谎,但一般情况下服务器都能检测到
  • RCPT TO: ——用来标志邮件接收者的地址,常用在MAIL FROM后,可以有多个RCPT TO
  • DATA ——将之后的数据作为数据发送,以.标志数据的结尾
  • REST ——重置会话,当前传输被取消
  • NOOP ——要求服务器返回OK应答,一般用作测试
  • QUIT ——结束会话
  • VRFY ——验证指定的邮箱是否存在,由于安全方面的原因,服务器大多禁止此命令
  • EXPN ——验证给定的邮箱列表是否存在,由于安全方面的原因,服务器大多禁止此命令
  • HELP ——查询服务器支持什么命令
SMTP协议存在的缺陷

  

电子邮件邮件身份验证技术

  SMTP不支持邮件加密、完整性校验和验证发件人身份。由于这些缺陷, 发送方电子邮件信息可能会被网络传输中的监听者截取流量读取消息内容导致隐私泄漏, 也可能遭受中间人攻击(Man-in-the-Middle attackMitM)导致邮件消息篡改, 带来网络钓鱼攻击,邮件的身份验证 –> SPFDKIMDMARC

1.SPF

  SPF,全称为 Sender Policy Framework,即发件人策略框架。根据 SMTP 的规则,发件人的邮箱地址是可以由发信方任意声明的,这显然是极不安全的。

SPF 出现的目的,就是为了防止随意伪造发件人

原理

  SPF 记录实际上是服务器的一个 DNS 记录,使用电子邮件的头部信息中的 ‘HELO’ 或 ‘Mail From’ 这两个邮件头里的域名来结合真正提供这个邮件的服务商 DNS 里面的记录去验证发送邮件服务器是否是冒充行为。原理其实很简单:

  假设邮件服务器收到了一封邮件,来自主机的 IP 是173.194.72.103,并且声称发件人为email@example.com。为了确认发件人不是伪造的,邮件服务器会去查询example.com的 SPF 记录。如果该域的 SPF 记录设置允许 IP 为173.194.72.103的主机发送邮件,则服务器就认为这封邮件是合法的;如果不允许,则通常会退信,或将其标记为垃圾/仿冒邮件。

  因为不怀好心的人虽然可以「声称」他的邮件来自example.com,但是他却无权操作example.com的 DNS 记录;同时他也无法伪造自己的 IP 地址。因此 SPF 是很有效的,当前基本上所有的邮件服务提供商(例如 Gmail、QQ 邮箱等)都会验证它。

记录查询

  spf记录本质上是服务器上的TXT类型的DNS记录,因此要查询SPF记录只需要使用dig命令进行查询:

1
2
3
>> dig -t txt 163.com		# 查询163邮箱的spf
ANSWER SECTION:
163.com.		1160	IN	TXT	"v=spf1 include:spf.163.com -all"  # 其中的一条记录,代表了spf规则遵从spf.163.com的,在其中没有包含的都不允许接收

  以查询xxx@163.com的spf记录为例,完整的查询过程如下:

1
2
3
4
5
6
7
8
9
>> dig -t txt 163.com		# 查询163邮箱的spf
ANSWER SECTION:
163.com.		1160	IN	TXT	"v=spf1 include:spf.163.com -all"  # 其中的一条记录,代表了spf规则遵从spf.163.com的,在其中没有包含的都不允许接收
>> dig -t txt spf.163.com 
ANSWER SECTION:
spf.163.com.		7283	IN	TXT	"v=spf1 include:a.spf.163.com include:b.spf.163.com include:c.spf.163.com include:d.spf.163.com include:e.spf.163.com -all"   # spf规则为a、b、c、d、e几个域名spf规则的和
>> dig -t txt a.spf.163.com   # 这里以a.spf.163.com为例,实际上还应对其他4个域名的spf记录进行访问
ANSWER SECTION:
a.spf.163.com.		60	IN	TXT	"v=spf1 ip4:220.181.12.0/22 ip4:220.181.31.0/24 ip4:123.125.50.0/24 ip4:220.181.72.0/24 ip4:123.58.178.0/24 ip4:123.58.177.0/24 ip4:113.108.225.0/24 ip4:218.107.63.0/24 ip4:123.58.189.128/25 ip4:123.126.96.0/24 ip4:123.126.97.0/24 -all"     # 明确了可以接收的ip地址
生效时间

SPF 记录本质上是一个 DNS 记录,所以并不是修改之后立即生效的——通常需要几个小时的时间。

人工检测通过SPF验证**

  这里可以使用一个在线验证网站进行查询:SPF Record Testing Tools

  首先对邮箱服务器对应的SPF记录进行查询(当然这里也可以使用dig命令进行手动查询):

image

  查询结果如下:

image

  输入IP、spf记录、发送域名、HELO内容进行SPF验证。

image

  最终查询结果如下:

image

  Results - PASS sender SPF authorized表示验证成功。验证失败则显示为Results - FAIL Message may be rejected

SPF存在的缺陷:

  与邮件转发器不兼容,转发电子邮件时,SPF检查可能会失败,因为SPF组件会对转发服务器(而不是原始发送服务器)进行身份验证。

2.DKIM

  DKIM全称DomainKeys Identified Mail,DKIM使用加密技术对发件人的身份进行验证,并对邮件完整性进行保护。

  启用DKIM的服务器当发送邮件时,邮件发送方生成一个DKIM-Signature,并使用私钥进行进行加密,并附在邮件的DATA部分的header中,当目标邮件服务器收到邮件后,将使用查询DKIM-Signature中的d字段,获取发送者的公钥,并验证DKIM有效性。

image

  其中:

  • d : 代表发送者的域名
  • h : 代表DKIM覆盖的头部字段列表
  • l :代表DKIM保证的有近头部长度
3.DMARC

  DMARC是建立在SPF和DKIM之上的一种身份验证机制,在使用DMARC机制的邮件服务器中,接收邮件时,接收邮件服务器首先查询From字段所对应的域的DMARC策略,获知应该如何处理认证失败的邮件,

  1. 身份对齐验证:检查From字段中的域与SPF或DKIM中的域是否匹配
    • 严格模式:From中的域名需要与SPF、DKIM中的域名完全一致
    • 宽松模式:只需要From中的注册域名(@后面的部分)与SPF、DKIM中保持一致
  2. SPF
  3. DKIM

  如果SPF或DKIM显示一个积极的结果,并且From中身份认证对齐成功,那么DMARC身份认证通过。DMARC身份认证比单独使用SPF或DKIM的鲁棒性更强,对于转发的电子邮件,SPF认证可能会失败,但是DKIM能够正常认证,DMARC还是能够正常通过。只有当两者都全部认证失败或身份对齐失败才会认为DMARC认证失败。

image

  SPF、DKIM认证的结果将显示在Authentication-Results中,DMARC将从中解析域名来与文件内容中的FORM字段进行对齐验证。

image

身份认证机制本身存在的问题

 虽然身份验证机制看起来很美好,但是在实际使用中由于身份认证本身存在的一些缺陷,仍然使攻击者能够通过一定的技术手段绕过认证,发送伪造邮件。

在身份认证保护下依旧产生发件人伪造的原因
  1. 不同身份认证组件之间的解释使用
  2. 邮件服务器和邮件客户端对特殊格式的不同解析

  3. 例如5节

1.HELO、MAIL FROM混乱

  SMTP提供了HELO和MAIL FROM两个字段来表示发件人的邮箱地址,SPF标准指出应当同时对两者进行验证,但是,检查MAIL FROM是强制的,而HELO只是推荐进行检查。

  DMARC标准指出DMARC验证应该使用MAIL FROM进行,当MAIL FROM为空才使用HELO进行验证。利用上面这两种机制,可使用下面的两种机制进行发件人欺骗:

1.1 不存在子域名

  这种攻击方式如下图所示,MAIL FROM输入为合法域名下的不存在子域名,因为不存在子域名的SPF策略,SPF无法对其进行验证,转而使用HELO字段进行SPF验证,而HELO字段是攻击者可以进行任意设置的,因此可以通过SPF验证;同时,因为MAIL FROm地址不为空,DMARC将继续使用MAIL FROM进行域对齐,因为二级域名为合法域,与FORM字段域名相同,因此DMARC域名对齐验证通过。邮件成功绕过DMARC身份认证。

image

1.2 “空” MAIL FROM

  在某些SPF实现中,将对(右侧内容视作注释内容,因此当使用(any@legitimate.com作为MAIL FROM地址时,SPF会将其视为空,然后使用HELO字段进行SPF验证,与上面相同,SPF通过验证并将验证结果传递给DMARC,在某些DMARC的验证中,仅仅将其视为普通地址进行与FROM域名进行域对齐身份验证,成功通过DMARC验证。

image

2. 身份验证组件与DNS组件不一致性

  这种身份认证绕过方式利用了身份认证组件和DNS组件之间的不一致性,攻击者制作模糊域,使身份验证组件认为他正在查询合法域,但DNS组件实际上在查询攻击者的域以获得策略记录。

  下图展示了这种攻击的实例,在C语言中,NUL(“\x00”)被认为是终止符,而在Perl和PHP中,将不被视为终止符,利用这种特性,攻击者对任意电子邮件可以构造绕过身份认证,首先他们使用自己的私有DKIM对邮件进行签名、生成DKIM-Signature标头,将标头中的d="legitimate.com",而s="atttacker.com.\x00.any",当Gmail服务器(Gmail服务器存在该问题)其DKIM组件查询s._domiankey.d,即attack.com.\x00.any._domainkey.legitimate来获取公钥,DNS组件进行对改地址进行解析时会将NUL字符视为终止符,因此将从attack.com获取公钥(攻击者的公钥),然后DKIM组件使用攻击者的公钥验证伪造邮件,错误的认为合法域名已经对该域进行可签名。另一方面,DMARC将使用d=legitimate.com域名与FORM域名对齐认证,二者相同,成功通过DMARC认证。

image

3. 认证结果注入
Authentication-Results

  SPF和DKIM以头部中的Authentication-Results将验证结果传递给DMARC组件,下面为Authentication-Results实例:

image

  其中spf=passdkim=pass表示邮件服务器通过了example.com的spf和dkim认证,smtp.mailfrom表示SPF组件验证的域名,header.d表示DKIM验证的域名,括号内的内容为备注。DMARC组件解析这个字段来进行DMAR域名对齐认证。

认证结果注入攻击

  这种身份认证的绕过方式来源于认证结果从一个组件传递到另一个组件的过程中,元字符的存在因起了身份认证类似于SQLi的攻击。对于某些特殊字符,SPF和DKIM会将这些字符视为数据,而DMARC组件在解析认证结果时将会将其视为控制信息,从而发生攻击。

3.1 DKIM认证结果注入

image

  攻击者使用自己的私钥生成DKIM-Signature标头,在标头中使用带d=,例如在下例中,d=legitimate.com(.attacker.com,DKIM组件将查询selector._domainkey.legitimate.com(. attacker.com,该域名在攻击者的控制之下,获取攻击者的公钥并通过dkim验证,返回的结果如下:

image

  当DMARC收到Authentication-Results,对d=xxx进行解析时,将会将其解析为legitmate.com,因为会将“(”后的内容视为注释,同时DMARC中解析到的域名与FORM标头匹配,成功通过DMARC身份认证。

“(双引号)和‘(单引号)与”(”具有相同的效果

3.2 SPF认证结果注入

  SPF认证结果注入与DKIM认证结果注入与DKIM结果认证类似,攻击者在MAIL FROM中使用相同的网址SPF认证注入攻击,例如下面的SPF认证结果注入。

image

  在一些邮件服务器中,对MAIL FROM的语法进行了一定的限制,MIAL FROM中不再能使用上面的特殊字符,但是我们可以使用另一种方式来进行SPF认证结果注入,如下图所示,邮件服务器进行SPF查询时将使用legitimate.com'@a.attack.com进行查询,该域名的SPF记录为攻击者设定,因此伪造的邮件能够成功通过SPF验证,而DMARC进行身份验证结果解析时,将'后的内容视为注释,使用域名legitimate.com与MAIL FROM域名进行对齐,成功通过DMARC认证。

image

UI不匹配问题

  由于电子邮件服务和邮件代理(MUA)分别处理消息,UI不匹配攻击利用了电子邮件服务器验证消息和MUA最终展示给用户的内容不一致来进行欺骗。

1.From头模糊

  经过研究发现,虽然SMTP标注中明确指出了电子邮件必须具有一个From header,但是仍存在大量电子邮件提供商和邮件代理并没有严格遵守这项规定,不会拒收这类邮件而是只是用第一个From header进行DMARC检查,这就造成了攻击者进行欺骗留下了机会。

1.1 多个From header

image

  这种攻击方式,首先邮件服务器需要与许多个From header,其次邮件服务器与电子邮件客户端需要具有不同的解析方式。攻击者在使用多个From header,例如上图中服务器使用第一个From字段进行DMARC对齐认证,而电子邮件客户端将第二个From header展示给用户。

1.2 使用空格跳过多From header检测

  SMTP标准规定每个email头部由字段名、冒号、字段对应的值组成,攻击者可以通过字段名之前或之后插入空格来违反此结构,那么不同的客户端、服务器将使用不同方式处理错误的标头,这为禁止使用多个From的邮件服务器使用多From header绕过认证提供了新的机会。

情形一

  虽然邮件服务器拒绝使用多个From头的电子邮件,但是攻击者使用折叠空间成功的From头绕过。因为服务器的DMARC组件可以识别出成功折叠的From头,验证attack.com,但是邮件代理客户端却将其作为未知头,而不是From头,因此将展示它认为只有一个From字段,即admin@legitimate.com,因此将admin@legitimate.com展示给客户。

这种情况要求请求邮件服务器能够成功识别出From头,而邮件代理客户端不能识别。

image

情形二:

  我们也可以利用电子邮件服务器进行邮件转发时特殊的行为来欺骗邮件代理客户端。以下图为例,Fastmail.com邮件服务器和Fastmail.com邮件代理客户端否无法识别包含空格的From header,而是将其当做前一个From的一部分进行处理,但是Fastmail.com邮件服务器对成功读取到的From header将进行规范化,即再转发邮件时删除其中的空格。这样MUA收到的邮件为标准的多From header问题。

image

情形三:利用备用From header

  在SMTP标准中,包含多个标识电子邮件发件人的角色,From代表编写消息的用户,Sender代表提交消息的用户,Resent-From代表代表转发消息的用户,通常只有From字段才在电子邮件认证和现实中起作用,但是如果攻击者故意制作没有From或无法识别的From字段,在某些情况下如果无法识别From字段,则使用备用头来标识发件人。

在测试的邮件服务器中,当无法读取到From字段时,Gmail显示resent-From来作为发件人展示,其他的都是只使用From进行DMARC认证,如果没有From字段,那么将不执行DMARC认证或返回None。

  如下面所示,Naver.com(电子邮件服务器)能够识别空格折叠的From头,认证attack值,但是Outlook(代理邮件客户端)无法识别它,因此将展示备用头Sender,造成发件人欺骗。

image

情形四:利用多种技术的融合来绕过更加严格的身份认证

  攻击者还可以使用多种技术融合来绕过更加复杂的身份验证,例如对于身份验证严格的Gmail邮件服务器,它拒绝多个From头,如果不存在From头邮件服务器将则根据MAIL From的值添加一个新的From头,攻击者同样可以使用多种技术的融合绕过,完成欺骗。

image

  绕过方式如上图所示,首先在邮件的第一个头部字段使用前置空格的From字段,Resent-From作为备用的发件人字段,MAIL FROM使用空值。Gmail邮件服务器能够正确识别出折叠空格的From字段的内容,进行DMARC认证,然后在邮件的头部添加Authentication-results,这将导致MUA将From解析成为一个折叠的内容,即Authentication-results的一部分,随后它将按照MAIL Form的值添加一个From字段,这里新添的From字段为空,因此MUA将忽略From,使用Resent-From进行展示,成功进行发件人欺骗。

2.邮件地址模糊
2.1 复杂的From header语法

  下图展示了标准具有单个From地址的From字段:

image

  主要包含四个部分:

  1. Display name: 可选,用于标识发件人的姓名,由于该地址不受身份认真的保护因此经常用于网路钓鱼中欺骗受害者。

  2. Route portion:

  3. Real address:
  4. Comments:
参考文献
  • xxx
  • xxx

相关文章:

邮件安全之发件人伪造

电子邮件工作原理 电子邮件传输过程中主要涉及到SMTP、IMAP、POP3三种协议,具体功能如下: SMTP:全称Simple Mail Transfer Protocol,即简单邮件传输协议,主要用于发送邮件,使用端口号25。 IMAP:全称Internet Mail Acce…...

前端八股——JS+ES6

前端八股:JSES6 说明:个人总结,用于个人复习回顾,将持续改正创作,已在语雀公开,欢迎评论改正。...

Qt QTreeWidget 总结

Qt QTreeWidget 总结 1. 概述 QTreeWidget 是 Qt 中用于显示树形结构的控件,继承自 QTreeView,但提供了更简单的接口。适合展示层级数据(如文件目录、组织结构)。每个节点是 QTreeWidgetItem 对象,支持文本、图标、复…...

Python常见面试题的详解16

1. 如何强行关闭客户端和服务器之间的连接? 在网络编程中,有时需要强行中断客户端和服务器之间的连接。对于基于 TCP 协议的连接,由于其面向连接的特性,需要采取特定的步骤来确保连接被正确关闭;而 UDP 是无连接协议&a…...

前端设计模式面试题及参考答案

目录 如何用闭包实现单例模式?列举两种实现方式 工厂模式与构造函数创建对象的核心区别是什么? 抽象工厂模式如何解决多平台 UI 组件兼容问题? 原型模式在前端框架中如何优化对象创建性能? 建造者模式如何实现复杂表单配置的链式调用? 单例模式在全局状态管理中的典型…...

Python Django系列—入门实例(二)

数据库配置 现在,打开 mysite/settings.py 。这是个包含了 Django 项目设置的 Python 模块。 默认情况下,​ DATABASES 配置使用 SQLite。如果你是数据库新手,或者只是想尝试 Django,这是最简单的选择。SQLite 包含在 Python 中…...

STM32-智能台灯项目

一、项目需求 1. 红外传感器检测是否有人,有人的话实时检测距离,过近则报警;同时计时,超过固定时间则报警; 2. 按键 1 切换工作模式:智能模式、按键模式、远程模式; 3. 智能模式下,根…...

HTML之JavaScript DOM操作元素(2)

HTML之JavaScript DOM操作元素(2) 4.增删元素var element document.createElement("元素名") 创建新元素父元素.appendChild(子元素) 在父元素中追加子元素父元素.insertBefore(新元素,参照元素) 在特定元素之前新增元…...

智能优化算法:莲花算法(Lotus flower algorithm,LFA)介绍,提供MATLAB代码

一、 莲花算法 1.1 算法原理 莲花算法(Lotus flower algorithm,LFA)是一种受自然启发的优化算法,其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性,即所谓的“莲花效应”,是由其叶片表面的微纳…...

【复习】计算机网络

网络模型 OSI 应用层:给应用程序提供统一的接口表示层:把数据转换成兼容另一个系统能识别的格式会话层:负责建立、管理、终止表示层实体之间的通信会话传输层:负责端到端的数据传输网络层:负责数据的路由、转发、分片…...

【R语言】读取CSV数据时,显示[1] PK...<0 行> (或0-长度的row.names)

一、问题 当我使用以下代码读取CSV数据后&#xff0c;发现使用head(data)显示[1] PK...<0 行> (或0-长度的row.names)&#xff0c;如下截图所示。 # 尝试读取文件 data <- read.csv("C:\\Users\\11300\\Desktop\\test.csv", header TRUE) # 检查数据 hea…...

CentOS环境变量配置+解析

环境变量的作用就是让系统快速通过你的命令找到你的可执行程序&#xff0c;windows系统里也同理&#xff0c;也就是你每次输入个命令&#xff0c;系统就会找环境变量里到底有没有叫这个命令进程的 一、环境变量配置 1.编辑配置文件 vim /etc/profile export PATH$PATH:$JAVA…...

最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程

ExoPlayer 是一个开源的 Android 媒体播放库&#xff0c;由 Google 开发和维护&#xff0c;用于替代 Android 系统自带的 MediaPlayer。它提供了更强大的功能、更好的性能和更高的灵活性&#xff0c;适用于各种复杂的媒体播放场景。所以被广泛用于各种播放器场景。 最近项目中…...

【蓝桥杯集训·每日一题2025】 AcWing 6134. 哞叫时间II python

6134. 哞叫时间II Week 1 2月20日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛&#xff0c;但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解&#xff0c;所以农夫约翰将竞赛…...

HTML/CSS中子代选择器

1.作用:选中指定元素中,符合要求的子元素. 子代选择器又称:子元素选择器,子选择器. 2.语法:选择器1>选择器2>选择器3>......选择器n 3.实例 <style>/* div中子代选择器 */div>a{color: red;}</style><div><a href"#">张三</…...

计算机毕业设计SpringBoot+Vue.jst网上购物商城系统(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

EasyRTC:全平台支持与自研算法驱动的智能音视频通讯解决方案

在智能硬件的浪潮中&#xff0c;设备之间的互联互通已成为提升用户体验的核心需求。无论是智能家居、智能办公&#xff0c;还是工业物联网&#xff0c;高效的音视频通讯和交互能力是实现智能化的关键。然而&#xff0c;传统音视频解决方案往往面临平台兼容性差、交互体验不佳以…...

C#: 日志函数

背景&#xff1a; 1.常见的官方日志模块项目过于复杂&#xff0c;且配置过于繁琐&#xff0c;针对这种现象&#xff0c;实现在大型项目中快速定位错误问题&#xff1b; 实现思路&#xff1a; 1.设置当前日志文件路径&#xff08;获取到当前文件应用程序路径 \ErrorLog) 2.判…...

PyTorch 是如何进行机器学习的

1. 机器学习的核心流程 机器学习的核心是通过数据训练模型&#xff0c;让模型学会从输入数据中提取规律&#xff0c;并对新数据做出预测。整个过程可以分为以下几个步骤&#xff1a; 准备数据&#xff1a;收集并整理数据&#xff0c;分为输入&#xff08;特征&#xff09;和输…...

Java中的Stream API:从入门到实战

引言 在现代Java开发中&#xff0c;Stream API 是处理集合数据的强大工具。它不仅让代码更加简洁易读&#xff0c;还能通过并行处理提升性能。本文将带你从基础概念入手&#xff0c;逐步深入Stream API的使用&#xff0c;并通过实战案例展示其强大功能。 1. 什么是Stream API…...

【蓝桥杯单片机】客观题

一、第十三届省赛&#xff08;一&#xff09; 二、第十三届省赛&#xff08;二&#xff09;...

Spring Boot 中使用 @Transactional 注解配置事务管理

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务&#xff1b;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污…...

嵌入式八股文(五)硬件电路篇

一、名词概念 1. 整流和逆变 &#xff08;1&#xff09;整流&#xff1a;整流是将交流电&#xff08;AC&#xff09;转变为直流电&#xff08;DC&#xff09;。常见的整流电路包括单向整流&#xff08;二极管&#xff09;、桥式整流等。 半波整流&#xff1a;只使用交流电的正…...

《论多源数据集成及应用》审题技巧 - 系统架构设计师

论多源数据集成及应用写作框架 一、考点概述 本论题“论多源数据集成及应用”主要考察的是计算机软件测试工程师在数据管理和集成方面的专业知识与实践能力。论题聚焦于信息爆炸时代企业、组织和个人所面临的数据挑战&#xff0c;特别是如何有效地收集、整理和清洗来自不同渠…...

怎么在Github上readme文件里面怎么插入图片?

环境&#xff1a; Github 问题描述&#xff1a; 怎么在Github上readme文件里面怎么插入图片&#xff1f; https://github.com/latiaoge/AI-Sphere-Butler/tree/master 解决方案&#xff1a; 1.相对路径引用 上传图片到仓库 将图片文件&#xff08;如 .png/.jpg&#xff…...

【NLP 31、预训练模型的发展过程】

人的行为&#xff0c;究竟是人所带来的思维方式不同还是与机器一样&#xff0c;刻在脑海里的公式呢&#xff1f; 只是因为不同的人公式不同&#xff0c;所以人的行为才不同&#xff0c;可这又真的是人引以为傲的意识吗&#xff1f; 人脑只是相当于一个大型、驳杂的处理器&#…...

【计算机网络】传输层TCP协议

传输层 - layer4 - TCP协议 传输层&#xff1a;位于ISO模型的第四层 ——>L4 tcp协议意为传输控制协议&#xff08;Transmission Control Protocol&#xff09; 提供端到端的连接 端口号范围&#xff1a;0-65535 &#xff08;2^16次方&#xff09; 一个应用程序(服务)会占用…...

vscode settings(二):文件资源管理器编辑功能主题快捷键

参考资料 Visual Studio Code权威指南 by 韩骏 一. 文件资源管理器 1.1 文件资源管理器隐藏文件夹 默认情况下&#xff0c;Visual Studio Code会在文件资源管理器中隐藏一些文件夹&#xff08;如.git文件夹&#xff09;​。可以通过files.exclude来配置要被隐藏的文件和文件…...

halcon机器视觉深度学习对象检测,物体检测

目录 效果图操作步骤软件版本halcon参考代码本地函数 get_distinct_colors()本地函数 make_neighboring_colors_distinguishable() 效果图 操作步骤 首先要在Deep Learning Tool工具里面把图片打上标注文本&#xff0c; 然后训练模型&#xff0c;导出模型文件 这个是模型 mod…...

go 反射 interface{} 判断类型 获取值 设置值 指针才可以设置值

内容包括 1. 用interface{}接收值 2. 判断interface{}的类型 switch 3. 打印interface{}的类型 4. 通过字符串对结构体&#xff0c;interface{}等进行设置值、获取值处理 示例代码 package mainimport ("fmt""log""reflect" )type Student…...

单臂路由

单臂路由&#xff08;Router on a Stick&#xff09;是一种网络配置方式&#xff0c;主要用于在单个物理接口上实现多个VLAN之间的路由。它通常用于交换机与路由器之间的连接&#xff0c;适用于VLAN间通信需求较小的情况。 工作原理 VLAN划分&#xff1a;交换机上配置多个VLAN…...

SpringBoot【实用篇】- 测试

文章目录 目标&#xff1a; 1.加载测试专用属性3.Web环境模拟测试2.加载测试专用配置4.数据层测试回滚5.测试用例数据设定 目标&#xff1a; 加载测试专用属性加载测试专用配置Web环境模拟测试数据层测试回滚测试用例数据设定 1.加载测试专用属性 我们在前面讲配置高级的…...

NutUI内网离线部署

文章目录 官网拉取源代码到本地仓库修改源代码打包构建nginx反向代理部署访问内网离线地址 在网上找了一圈没有写NutUI内网离线部署的文档&#xff0c;花了1天时间研究下&#xff0c;终于解决了。 对于有在内网离线使用的小伙伴就可以参考使用了 如果还是不会联系UP主:QQ:10927…...

【深度学习】Adam和AdamW优化器有什么区别,以及为什么Adam会被自适应学习率影响

Adam 和 AdamW 的主要区别在于 权重衰减&#xff08;Weight Decay&#xff09; 的实现方式&#xff0c;具体如下&#xff1a; 1. 权重衰减&#xff08;Weight Decay&#xff09;处理方式 Adam&#xff1a;采用 L2 正则化&#xff0c;通过在梯度更新时手动添加 weight_decay 项…...

Pytorch的F.cross_entropy交叉熵函数

参考笔记&#xff1a;pytorch的F.cross_entropy交叉熵函数和标签平滑函数_怎么给crossentropyloss添加标签平滑-CSDN博客 先来讲下基本的交叉熵cross_entropy&#xff0c;官网如下&#xff1a;torch.nn.functional.cross_entropy — PyTorch 1.12 documentation torch.nn.fun…...

一文讲解Redis为什么读写性能高以及I/O复用相关知识点

Redis为什么读写性能高呢&#xff1f; Redis 的速度⾮常快&#xff0c;单机的 Redis 就可以⽀撑每秒十几万的并发&#xff0c;性能是 MySQL 的⼏⼗倍。原因主要有⼏点&#xff1a; ①、基于内存的数据存储&#xff0c;Redis 将数据存储在内存当中&#xff0c;使得数据的读写操…...

[特殊字符] Elasticsearch 双剑合璧:HTTP API 与 Java API 实战整合指南

&#x1f680; Elasticsearch 双剑合璧&#xff1a;HTTP API 与 Java API 实战整合指南 一、HTTP API 定义与用途 Elasticsearch 的 HTTP API 是基于 RESTful 接口设计的核心交互方式&#xff0c;支持通过 URL 和 JSON 数据直接操作索引、文档、集群等资源。适用于快速调试、…...

某手sig3-ios算法 Chomper黑盒调用

Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架&#xff0c;Chomper 是一个模拟执行iOS可执行文件的框架&#xff0c;类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法&#xff0c;初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...

蓝桥杯之阶段考核

&#x1f4d6; Day 7&#xff1a;阶段考核 - 蓝桥杯官方模拟赛&#xff08;限时 4 小时&#xff09; &#x1f4d6; 一、如何高效完成模拟赛&#xff1f; 模拟赛是一种接近真实竞赛的训练方式。要高效完成模拟赛&#xff0c;需要掌握以下策略&#xff1a; 1. 赛前准备 ✅ 环…...

DeepSeek掘金——VSCode 接入DeepSeek V3大模型,附使用说明

VSCode 接入DeepSeek V3大模型,附使用说明 由于近期 DeepSeek 使用人数激增,服务器压力较大,官网已 暂停充值入口 ,且接口响应也开始不稳定,建议使用第三方部署的 DeepSeek,如 硅基流动 或者使用其他模型/插件,如 豆包免费AI插件 MarsCode、阿里免费AI插件 TONGYI Lin…...

华为昇腾服务器(固件版本查询、驱动版本查询、CANN版本查询)

文章目录 1. **查看固件和驱动版本**2. **查看CANN版本**3. **其他辅助方法**注意事项 在华为昇腾服务器上查看固件、驱动和CANN版本的常用方法如下&#xff1a; 1. 查看固件和驱动版本 通过命令行工具 npu-smi 执行以下命令查看当前设备的固件&#xff08;Firmware&#xff0…...

红帽7基于kickstart搭建PXE环境

Kickstart 文件是一种配置文件&#xff0c;用于定义 Linux 系统安装过程中的各种参数&#xff0c;如分区、网络配置、软件包选择等。system-config-kickstart 提供了一个图形界面&#xff0c;方便用户快速生成这些配置文件。 用户可以通过图形界面进行系统安装的详细配置&…...

【Python爬虫(58)】从0到1:Scrapy实战爬取大型新闻网站

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

DeepSeek使用从入门到精通

1. DeepSeek概述 - DeepSeek是国产大模型&#xff0c;提供网页版和App版。因其强大功能&#xff0c;遭受网络攻击&#xff0c;但国内用户可直接使用。 2. 入门技巧 - 忘掉复杂提示词&#xff1a;用简洁明了的需求指令&#xff0c;AI能自我思考并生成优质内容 - 明确需求&#…...

【分布式数据一致性算法】Gossip协议详解

在分布式系统中&#xff0c;多个节点同时提供服务时&#xff0c;数据一致性是核心挑战。在多个节点中&#xff0c;若其中一个节点的数据发生了修改&#xff0c;其他节点的数据都要进行同步。 一种比较简单粗暴的方法就是 集中式发散消息&#xff0c;简单来说就是一个主节点同时…...

一、初始爬虫

1.爬虫的相关概念 1.1 什么是爬虫 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟浏览器发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动地爬取互联网信息的程序。 原则上&#xff0c;只要是浏览器…...

C语言番外篇(3)------------>break、continue

看到我的封面图的时候&#xff0c;部分读者可能认为这和编程有什么关系呢&#xff1f; 实际上这个三个人指的是本篇文章有三个部分组成。 在之前的博客中我们提及到了while循环和for循环&#xff0c;在这里面我们学习了它们的基本语法。今天我们要提及的是关于while循环和for…...

ipad连接电脑断断续续,不断弹窗的解决办法

因为ipad air 屏幕摔坏&#xff0c;换了一个内外屏&#xff0c;想用爱思检验一下屏幕真伪&#xff0c; 连接电脑时&#xff0c;断断续续&#xff0c;连上几秒钟然后就断开&#xff0c;然后又连上 然后又断开&#xff0c;不断地弹出信任的弹窗。 刚开始以为是数据线问题&#x…...

dockerfile构建haproxy

1. 结构目录 [rootlocalhost ~]# tree haproxy/ haproxy/ ├── dockerfile └── files├── haproxy-2.5.0.tar.gz├── haproxy.cfg├── install.sh└── start.sh1 directory, 5 files [rootlocalhost ~]# [rootlocalhost ~]# cd haproxy/ [rootlocalhost haproxy]…...

创建第一个 Maven 项目(一)

一、引言 在 Java 开发的广袤天地中&#xff0c;Maven 宛如一位全能的管家&#xff0c;发挥着举足轻重的作用。它是一个基于项目对象模型&#xff08;POM&#xff09;的项目管理和构建自动化工具&#xff0c;极大地简化了 Java 项目的开发流程。 Maven 的核心优势之一在于其强…...