nftables(4)表达式(2)主要表达式(PRIMARY EXPRESSIONS)

简介

上篇文章已经介绍了数据类型,如INTERGER TYPE、BITMASK TYPE、STRING TYPE、LINK LAYER ADDRESS TYPE、 IPV4 ADDRESS TYPE、 IPV6 ADDRESS TYPE、BOOLEAN TYPE、ICMP TYPE、CONNTRACK TYPES等。那么本篇文章主要介绍PRIMARY表达式的相关内容。

PRIMARY EXPRESSIONS

在防火墙规则配置中,主要表达式(Primary Expressions)是最低阶的表达式,它们代表数据包负载中的常量或单个数据项、元数据,或者来自有状态模块的数据。这些表达式是构建更复杂表达式的基础,用于在防火墙规则、路由决策或数据包处理逻辑中指定具体的条件或值。

META EXPRESSIONS

元数据表达式(Meta Expressions)指的是与数据包相关联的元数据信息。这些元数据包括数据包的来源、目标、接口信息、时间戳、优先级等,对于制定复杂的过滤和路由规则非常有用。元表达式允许防火墙规则基于数据包的元数据来匹配和处理数据包,而不是仅仅基于数据包的内容。

主要表达式和元数据表达式在网络规则制定中具有互补的作用,前者通常用于处理数据包的内容或单个数据,而后者用于描述数据包的元数据信息,帮助用户更准确地定义和处理数据包的行为。

meta {length | nfproto | l4proto | protocol | priority}
[meta] {mark | iif | iifname | iiftype | oif | oifname | oiftype | skuid | skgid | nftrace | rtclassid | ibrname | obrname | pkttype | cpu | iifgroup | oifgroup | cgroup | random | ipsec | iifkind | oifkind | time | hour | day }

类型

  • 未限定元数据表达式(Unqualified Meta Expressions):这些表达式直接使用元数据关键字(如markiif等),而不需要前缀meta。然而,在某些上下文中,为了清晰或遵循特定的语法规则,它们也可以被写作限定的形式。

  • 限定的元数据表达(Qualified Meta Expressions):这些表达式在元数据关键字前加上meta前缀,以明确指定它们是对元数据的引用。虽然大多数元数据项可以直接使用,但使用meta前缀可以提高代码的可读性和一致性。

常见的元数据项

  • l4proto:用于匹配数据包中的特定传输层协议(如TCP、UDP等)。对于IPv6数据包,它会跳过任何扩展头。

  • iif/oif 与 iifname/oifname:这些用于匹配数据包进入或离开的网络接口。iifoif基于接口索引进行匹配,而iifnameoifname则基于接口名称进行匹配。接口索引在接口被重命名时不会改变,但接口名称可能会改变。因此,在接口名称可能发生变化的情况下(如动态创建的接口),使用接口名称进行匹配可能更为灵活。

  • mark, nftrace, rtclassid 等:这些元数据项用于高级的网络处理任务,如数据包标记、跟踪和路由类设置。

动态接口和通配符匹配

  • 对于动态创建的接口(如tun/tap接口或拨号接口ppp),使用iifnameoifname进行匹配可能更为合适,因为它们不依赖于接口在系统启动时的存在。
  • iifnameoifname中,可以使用通配符(如星号*)来匹配接口名称的前缀。但是,请注意,与iptables不同,nftables不接受仅由通配符字符组成的接口名称。如果确实需要匹配字面量的星号字符,可以使用反斜杠\进行转义。

元数据表达式类型

关键字描述类型
length数据包的长度(以字节为单位)integer (32-bit)
nfproto真实的钩子协议族(仅在inet表中有效)integer (32-bit)
l4proto第四层协议(跳过IPv6扩展头部)integer (8-bit)
protocolEtherType协议值ether_type
priorityTC数据包优先级tc_handle
mark数据包标记mark
iif输入接口索引iface_index
iifname输入接口名称ifname
iiftype输入接口类型iface_type
oif输出接口索引iface_index
oifname输出接口名称ifname
oiftype输出接口硬件类型iface_type
sdif从属设备输入接口索引iface_index
sdifname从属设备接口名称ifname
skuid与原始套接字关联的UIDuid
skgid与原始套接字关联的GIDgid
rtclassid路由领域realm
ibrname输入桥接接口名称ifname
obrname输出桥接接口名称ifname
pkttype数据包类型pkt_type
cpu处理数据包的CPU编号integer (32-bit)
iifgroup输入设备组devgroup
oifgroup输出设备组devgroup
cgroup控制组IDinteger (32-bit)
random伪随机数integer (32-bit)
ipsec数据包是否经过IPsec加密boolean (1-bit)
iifkind输入接口类型(更详细)字符串/其他
oifkind输出接口类型(更详细)字符串/其他
time数据包接收的绝对时间Integer (32-bit) 或 字符串
day一周中的哪一天Integer (8-bit) 或 字符串
hour一天中的哪个小时字符串

元表达式特定类型

类型        描述
iface_index接口索引(32位数字)。可以以数字形式指定,也可以作为现有接口的名称指定。
ifname接口名称(16字节字符串)。不需要实际存在。
iface_type接口类型(16位数字)。
uid用户ID(32位数字)。可以以数字形式指定,也可以作为用户名指定。
gid组ID(32位数字)。可以以数字形式指定,也可以作为组名指定。
realm路由领域(32位数字)。可以以数字形式指定,也可以作为/etc/iproute2/rt_realms中定义的符号名称指定。
devgroup_type设备组(32位数字)。可以以数字形式指定,也可以作为/etc/iproute2/group中定义的符号名称指定。
pkt_type数据包类型:host(发送给本地主机)、broadcast(发送给所有)、multicast(发送给组)、other(发送给另一台主机)。
ifkind接口类型(16字节字符串)。参见ip-link(8)手册页中的TYPES列表。
time可以是整数或ISO格式的日期。例如:"2019-06-06 17:00"。小时和秒是可选的,如果省略,则默认为午夜。以下三个是等价的:"2019-06-06"、"2019-06-06 00:00"和"2019-06-06 00:00:00"。当给定整数时,假定为UNIX时间戳。
day可以是星期几的名称("Monday"、"Tuesday"等),或者是0到6之间的整数。字符串匹配不区分大小写,并且不需要完全匹配(例如,"Mon"可以匹配"Monday")。当给定整数时,0代表星期日,6代表星期六。
hour表示24小时制中的小时的字符串。秒是可选的。例如,17:00和17:00:00是等价的。

使用举例

# 限定元表达式
filter output meta oif eth0  # 此规则指定输出接口为 "eth0" 的数据包
filter forward meta iifkind { "tun", "veth" } #  此规则表示转发数据包中输入接口种类为 "tun" 或 
"veth" 的数据包将被匹配# 不限定元表达式
filter output oif eth0 #直接使用了 meta 键指定输出接口为 "eth0" 的数据包raw prerouting meta ipsec exists accept #这条规则是在原始表(raw table)的 prerouting 链中,
检查数据包是否经过了 IPsec 处理。如果数据包已经经过了 IPsec 加密处理,存在相应的元数据信息,则执
行 accept 操作,即允许数据包继续处理。

Socket expression 

Socket expression 是一种在网络过滤或监控系统中使用的表达式,它允许你根据特定的条件来搜索或匹配已经打开的 TCP/UDP 套接字(socket)及其相关属性。这些属性可能与经过网络接口的数据包相关联。Socket expression 提供了强大的灵活性,用于在网络数据包处理流程中实施复杂的规则或策略。

搜索已打开的套接字

Socket expression 允许你查找已建立(established)或已绑定(bound,但不一定处于监听状态)的套接字。这些套接字可能绑定到特定的 IP 地址和端口上,也可能绑定到非本地(即非 127.0.0.1 或 ::1)地址上。这种能力对于监控特定应用程序的网络活动或实施基于套接字的网络策略非常有用。

匹配套接字属性

除了简单地查找套接字外,Socket expression 还可以用来匹配套接字的特定属性。这些属性可能包括套接字的类型(TCP 或 UDP)、状态(如已建立、监听等)、绑定的 IP 地址和端口等。通过匹配这些属性,你可以更精确地控制哪些数据包应该被允许或拒绝。

cgroupv2 套接字匹配

另一个高级功能是匹配套接字所属的 cgroupv2 层级。cgroupv2(Control Groups version 2)是 Linux 内核中的一种功能,用于限制、记录和隔离进程组所使用的物理资源(如 CPU、内存、网络带宽等)。通过 Socket expression,你可以根据套接字所属的 cgroupv2 层级来匹配数据包。这对于实施基于进程组或容器的网络策略特别有用。

socket {transparent | mark | wildcard}
socket cgroupv2 level NUM
名称描述类型
transparent在找到的套接字中,IP_TRANSPARENT套接字选项的值。它可以是0或1。boolean
mark套接字的标记值(SOL_SOCKET, SO_MARK)。mark
wildcard表示套接字是否绑定了通配符地址(例如,0.0.0.0或::0)。boolean
cgroupv2此套接字所属的cgroup v2的层次结构(或标识符)。cgroupv2

使用举例

# 标记与透明套接字相对应的数据包。"socket wildcard 0"意味着不匹配绑定到通配符地址的监听套接字(这通常是您想要的)。  
table inet x {  chain y {  type filter hook prerouting priority mangle; policy accept;  # 如果数据包对应于一个启用了IP_TRANSPARENT选项的套接字,并且该套接字不是绑定到通配符地址的,  # 则将该数据包的标记设置为0x00000001,并接受该数据包。  socket transparent 1 socket wildcard 0 mark set 0x00000001 accept  }  
}  # 追踪标记值为15的套接字对应的数据包。  
table inet x {  chain y {  type filter hook prerouting priority mangle; policy accept;  # 如果数据包的标记值等于0x0000000f,则设置nftrace标志以进行追踪(这通常需要额外的内核配置或工具来实际捕获追踪信息)。  socket mark 0x0000000f nftrace set 1  }  
}  # 将数据包的标记设置为套接字的标记。  
table inet x {  chain y {  type filter hook prerouting priority mangle; policy accept;  # 如果数据包的目标端口是8080(TCP),则将数据包的标记设置为与该数据包相关联的套接字的标记。  tcp dport 8080 mark set socket mark  }  
}  # 对cgroupv2 "user.slice"在层级1上的数据包进行计数。  
table inet x {  chain y {  type filter hook input priority filter; policy accept;  # 对于输入方向的数据包,如果该数据包对应的套接字属于cgroupv2层级1下的"user.slice",  # 则对该数据包进行计数(这通常用于监控和统计特定cgroup的网络活动)。  socket cgroupv2 level 1 "user.slice" counter  }  
}

osf expression

操作系统指纹(Operating System Fingerprinting),用于识别和确定目标系统的操作系统类型及其版本。这种技术通过分析从目标系统发出的网络数据包中的特定信息来实现。这种技术涉及分析具有 SYN 位设置的数据包中的某些特征,以推断远程主机上运行的操作系统详情。比较通常关注的数据包属性包括窗口大小、最大段大小(MSS)、选项及其顺序、不分片(DF)标志以及其他 TCP/IP 数据包属性。通过检查这些数据包属性,并将它们与已知与各种操作系统相关的模式进行比较,可以了解特定设备上可能运行的操作系统类型,而无需主动从事任何侵入式的扫描或探测活动。

osf [ttl {loose | skip}] {name | version}

osf属性

名称描述类型
ttl对数据包的生存时间(TTL)进行检查,以确定操作系统类型。TTL(Time-To-Live)是数据包在网络中可以经过的路由器数量的最大值。string
version对数据包进行操作系统版本的检查。这通常涉及对数据包中特定字段的详细分析,以推断操作系统的具体版本。
name要匹配的操作系统签名的名称。这些签名通常基于操作系统在网络通信中特有的行为或数据包特征。所有签名都可以在pf.os文件(或类似文件,取决于使用的工具或系统)中找到。如果表达式无法检测到匹配的操作系统签名,则可以使用"unknown"来表示未知或无法识别的操作系统。string

可用的TTL值检查选项

如果没有传递TTL属性,则会创建一个真实的IP头部,并直接进行TTL值的指纹比对。这种方法通常适用于局域网(LANs)。

  • loose(宽松):检查IP头部的TTL值是否小于指纹中的TTL值。这种方法适用于全局可路由的地址,因为它允许一定的TTL值差异,可能是由于数据包在到达目标之前经过了不同数量的路由器。
  • skip(跳过):完全不进行TTL值的比较。这意味着在操作系统指纹识别过程中,TTL值将不会被用作判断依据。

使用举例

# 在不比较 TTL 的情况下接受与 "Linux" 操作系统类型签名匹配的数据包。
# 如果数据包的操作系统指纹与 "Linux" 匹配,那么这个规则允许通过并执行默认策略(accept)
table inet x {chain y {type filter hook input priority filter; policy accept;osf ttl skip name "Linux"}
}

fib expression

FIB(Forwarding Information Base,转发信息库)是路由器用来决定如何转发数据包到目的地的核心数据库。它包含了关于如何基于数据包的目的地地址将其路由到正确的下一跳地址或输出接口的详细信息。

fib {saddr | daddr | mark | iif | oif} [. ...] {oif | oifname | type}
关键字描述类型
oif输出接口索引integer (32 bit)
oifname输出接口名称string
type地址类型fib_addrtype*

使用举例

# 检查数据包是否有反向路径。它基于源地址和输入接口查找路由信息。如果找不到匹配的路由,输出接口索引将为零,然后将对应的数据包丢弃。
filter prerouting fib saddr . iif oif missing drop
# 在这个示例中,'saddr . iif' 根据源地址和输入接口查找路由信息。
# oif 从路由信息中选择输出接口索引。
# 如果未找到源地址/输入接口组合的路由,则输出接口索引为零。
# 如果将输入接口作为输入键的一部分指定,则输出接口索引始终与输入接口索引相同或为零。
# 如果仅给出 'saddr oif',那么 oif 可以是任何接口索引或零。# 对于目的地址不在传入接口上配置的数据包进行处理。如果目的地址不是本地、广播或多播类型,则将这些数据包丢弃。
filter prerouting fib daddr . iif type != { local, broadcast, multicast } drop#在特定的 'blackhole' 表(0xdead)中执行查找操作,根据目的地址的标记类型来进行不同的操作:blackhole 表示丢弃数据包,prohibit 表示跳转到受限制操作,unreachable 表示丢弃数据包。
filter prerouting meta mark set 0xdead fib daddr . mark type vmap { blackhole : drop, prohibit : jump prohibited, unreachable : drop }

 routing expression

路由表达式是指与数据包相关联的路由数据。

rt [ip | ip6] {classid | nexthop | mtu | ipsec}

路由表达式类型

关键字描述类型
classid路由领域(Routing realm),用于分类或标识路由的特定组或区域。realm 路由领域(Routing Realm)(32位数字)。可以指定为数字,或者在/etc/iproute2/rt_realms文件中定义的符号名称。通过为路由分配不同的领域值,可以更容易地管理和控制数据包的路由选择。这些领域值可以是任意32位数字,但为了便于理解和记忆,可以在/etc/iproute2/rt_realms文件中为这些数字定义符号名称。这样,在配置路由时,就可以使用这些符号名称来代替数字,从而使配置更加清晰和易于维护。realm
nexthop路由的下一跳地址,可以是IPv4或IPv6地址ipv4_addr/ipv6_addr
mtu路由的TCP最大报文段大小(TCP Maximum Segment Size),用于TCP连接的MTU发现integer (16 bit)
ipsec指示路由是否通过IPsec隧道或传输模式进行boolean(真/假)

ipsec expression

ipsec表达式是指与报文相关联的ipsec数据。
需要使用in或out关键字来指定表达式是应该检查入站策略还是出站策略。in关键字可用于预路由、输入和转发钩子。out关键字适用于转发、输出和发送后钩子。可选关键字spnum可用于匹配链中的特定状态,默认值为0。

ipsec {in | out} [ spnum NUM ]  {reqid | spi}
ipsec {in | out} [ spnum NUM ]  {ip | ip6} {saddr | daddr}

Ipsec expression types

KeywordDescriptionType
reqidRequest IDinteger (32 bit)
spiSecurity Parameter Indexinteger (32 bit)
saddrSource address of the tunnelipv4_addr/ipv6_addr
daddrDestination address of the tunnelipv4_addr/ipv6_addr

numgen expression 

numgen 表达式用于创建一个数字生成器,其操作模式由 inc(递增)或 random(随机)关键字控制。这个表达式在需要动态生成一系列数字时非常有用,特别是在编程、脚本编写、或任何需要自动化数值处理的场景中。

numgen {inc | random} mod NUM [ offset NUM ]numgen:这是启动数字生成器的关键字。
{inc | random}:这指定了生成器的操作模式。inc 表示递增模式,其中生成的每个数字都是前一个数字的递增值;random 表示随机模式,其中每次生成的数字都是随机的。
mod NUM:这指定了一个上限(模数),生成的数字不会超过这个值。模数(NUM)用于确保生成的数字在一个指定的范围内。
[offset NUM]:这是一个可选参数,允许你为生成的数字添加一个固定的偏移量。这意味着每个生成的数字都会先按照 inc 或 random 模式计算,然后再加上这个偏移量。

使用举例

add rule nat prerouting dnat to numgen inc mod 2 map \{ 0 : 192.168.10.100, 1 : 192.168.20.200 }
目的:这个规则的目的是在192.168.10.100和192.168.20.200这两个IP地址之间实现轮询(Round-Robin)负载均衡。
机制:通过numgen inc mod 2,每次请求都会生成一个递增的数字(从0开始),然后这个数字对2取模,结果只能是0或1。根据这个结果,请求会被重定向到map中指定的IP地址。
映射:如果生成的数字是0,则请求被重定向到192.168.10.100;如果是1,则重定向到192.168.20.200。由于数字是递增的,并且每次都对2取模,因此这实现了在两个IP地址之间的交替选择,即轮询。add rule nat prerouting dnat to numgen random mod 10 map \{ 0-2 : 192.168.10.100, 3-9 : 192.168.20.200 }
目的:这个规则的目的是根据概率将请求分配到两个IP地址,但带有一定的偏置,使得192.168.20.200接收的请求更多。
机制:通过numgen random mod 10,每次请求都会生成一个0到9之间的随机数字。然后,这个数字被用来在map中查找对应的IP地址。
映射:如果生成的数字在0到2之间(包含0和2),则请求被重定向到192.168.10.100;如果数字在3到9之间(包含3和9),则请求被重定向到192.168.20.200。由于3到9的范围比0到2的范围大,因此192.168.20.200接收的请求数量大约是192.168.10.100的三倍(8/3 ≈ 2.67,但实际上由于随机性,比例可能略有不同)。

hash expressions

jhash(通常称为Jenkins Hash)和symhash(对称哈希)是两种常用的哈希函数,用于生成一个数字,该数字可以作为决策的依据,比如决定将数据包发送到哪个服务器。这些哈希函数通过特定的算法处理输入数据(如数据包头部信息),并输出一个固定范围的数值。

Jenkins Hash(jhash)

特点

  • 灵活性jhash允许你通过表达式指定数据包头部中哪些参数用于哈希计算,甚至可以进行拼接(concatenation)来创建更复杂的输入。
  • 参数
    • 输入数据:这是你想要哈希的数据,可能是数据包头部的字段拼接而成的字符串。
    • 模数(modulus):通过mod关键字指定的一个上限值,确保哈希函数返回的数字不会超过这个值。这对于确保负载均衡的均匀分布非常关键。
    • 种子(seed)(可选):一个初始值,用于哈希函数的计算中。不同的种子值会导致相同的输入数据产生不同的哈希值,这有助于在分布式系统中避免哈希碰撞。
    • 偏移量(offset)(可选):允许你将返回的哈希值增加一个固定的偏移量,这在某些特定场景下可能有用。

应用场景

  • 在负载均衡器中,jhash可以用来根据数据包的某些特征(如源IP、目的IP、端口号等)计算出一个哈希值,然后根据这个哈希值决定将数据包转发到哪个后端服务器。

对称哈希(symhash)

特点

  • 对称性:尽管symhash的确切特性可能因实现而异,但“对称”一词通常意味着该哈希函数在某些方面是对称的,比如输入数据的微小变化可能导致哈希值在数值空间中的相对位置发生对称变化。然而,这只是一个概念性的解释,具体实现可能有所不同。
  • 参数:与jhash类似,symhash也可能需要输入数据、模数、种子和偏移量等参数。

应用场景

  • jhash相似,symhash也可以用于负载均衡中,通过哈希数据包的特征来决定其路由。不过,由于symhash的具体实现和特性可能因环境而异,因此其在实际应用中的表现也可能有所不同。

举例使用

#对于所有进入网络的数据包,系统会根据数据包的源IP地址(ip saddr)使用jhash来计算一个哈希值。然后,这个哈希值会被mod 2操作,结果是0或1。根据这个结果,数据包的目的地址(DNAT)会被重定向到两个IP地址之一:
如果哈希值mod 2的结果是0,数据包的目的地址将被更改为192.168.10.100。
如果哈希值mod 2的结果是1,数据包的目的地址将被更改为192.168.20.200。
add rule nat prerouting dnat to jhash ip saddr mod 2 map \{ 0 : 192.168.10.100, 1 : 192.168.20.200 }# 使用 symhash 函数,根据对称性哈希算法,在两个指定的 IP 地址(192.168.10.100 和 192.168.20.200)之间进行负载均衡。
对称哈希函数考虑更多的对称性和平衡性,以确保流量被均匀地分配到这两个 IP 地址上,从而实现对称性负载均衡。
add rule nat prerouting dnat to symhash mod 2 map \{ 0 : 192.168.10.100, 1 : 192.168.20.200 }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/869569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP充电桩小程序系统源码

绿色出行新伴侣!充电桩小程序,让充电不再烦恼✨ 🔋 开篇:告别电量焦虑,充电桩小程序来救场! 在这个电动车日益普及的时代,电量不足成了不少车主的“心头大患”。但别担心,充电桩小…

记一次mysql导出到达梦数据库

DM8管理工具 DM管理工具(官方)DBeaver - jdbc驱动 MySql迁移到DM8 使用官方DM数据迁移工具 新建迁移工程选择MySQL>DM填写mysql连接信息、添加dm连接信息执行 DM8数据脚本制作过程 使用DM管理工具 导出全部:进入对应模式>表>选…

nprogress进度条插件

打开一个页面时,往往会伴随一些请求,并且会在页面上方出现进度条。它的原理时,在我们发起请求的时候开启进度条,在请求成功后关闭进度条,所以只需要在request.js中进行配置。 如下图所示,我们页面加载时发起…

grblHAL的代码学习笔记和解读

源代码在 https://github.com/grblHal 目前日期2024/07/09 或许几年以后代码会做变更. 仅供参考. grbl是个很好的库. grblHAL是在grbl的基础上改进来的. grbl的板子通过串口或者SD卡或网络与上位机进行通信, 上位机负责查看和人机交互. 上位机把CAM软件生成的代码读入以后,转换…

docker pull rabbimq镜像失败

在使用docker pull rabbitmq的镜像的时候,找了好多源,都报错如下: Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.dock…

3.上传图片(阿里云空间,oss验证)

笔记 20240710 未验证&#xff0c;现在还没有阿里云空间&#xff0c;等买个sit环境就可以验证一下。 前端 页面 <!--页面--> <el-form-item label"优惠券图片" prop"couponImg"><single-upload v-model"dataForm.couponImg"&g…

【R语言+Gephi】利用R语言和Gephi实现共发生网络的可视化

【R语言Gephi】利用R语言和Gephi实现共发生网络的可视化 注&#xff1a;本文仅作为自己的学习记录以备以后复习查阅 一 概述 Gephi是一款开源免费的多平台网络分析软件&#xff0c;在Windows、Linux和Mac os上均可以运行&#xff0c;像他们官网所说的&#xff0c;他们致力于…

【深度学习】Pytorch完成线性回归!

&#x1f34a;嗨&#xff0c;大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; )&#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。 易编橙&#xff1a;一个帮助编程小…

提升困难生学工支持:智慧校园的新功能介绍

智慧校园的学工管理系统内嵌的困难生信息管理功能&#xff0c;是一个综合性的服务平台&#xff0c;专注于精准识别校园内的经济困难学生&#xff0c;并给予他们必要的帮助与关怀&#xff0c;确保每位学生都能在公平的环境中追求学业和个人成长。这一功能通过一系列信息化手段&a…

标准立项 | 深度脱氨生物填料选型指南

编制单位&#xff1a;北京科净源科技股份有限公司、中国地质大学(北京)、中华环保联合会水环境治理专业委员会、清华大学、北京师范大学、中国环境科学研究院、清华大学、天津高端装备研究院、中车环境科技有限公司、云南滇池水务股份有限公司等。

职升网:考取专科学历的途径包括以下这些!

高考统招&#xff1a; 每年6月举行的全国统一高考&#xff0c;是获得专科学历的传统途径。 考生需参加由教育部组织的统一考试&#xff0c;按照分数由高到低依次录取。 适合高中毕业生或具有同等学历的学生。 自学考试&#xff1a; 又称自考&#xff0c;是一种没有入学考试…

C/C++ list模拟

模拟准备 避免和库冲突&#xff0c;自己定义一个命名空间 namespace yx {template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;};template<class T>class list{typedef ListNode<T> Node;public:private:Node* _…

ArcGIS的智慧与情怀

初识ArcGIS 在这个信息化的时代&#xff0c;ArcGIS如同一位智者&#xff0c;静静地伫立在地理信息系统的巅峰。初识它时&#xff0c;我仿佛走进了一片未知的领域&#xff0c;心中充满了好奇与期待。ArcGIS&#xff0c;这款专业的地理信息系统软件&#xff0c;凭借其强大的功能…

小米恢复联系人,跟着这2个步骤,让你的社交重回巅峰

当你突然发现小米手机里的联系人列表变得空空如也&#xff0c;是不是感觉就像失去了与外界沟通的“秘密武器”&#xff1f;别担心&#xff0c;这并不意味着你真的失去了他们。他们可能只是藏在了手机里的某个神秘角落&#xff0c;等待着你的召唤。接下来&#xff0c;小编将会介…

瓦罗兰特游戏帧数低怎么办 瓦罗兰特游戏帧率提不上去怎么解决

瓦罗兰特是一款由拳头游戏&#xff08;Riot Games&#xff09;开发的5v5英雄射击游戏。结合了MOBA元素&#xff0c;每个角色都拥有四个独特的技能&#xff1b;提供了多种游戏模式&#xff0c;如5V5战术射击等&#xff1b;角色和皮肤设计丰富。游戏中&#xff0c;玩家将扮演各具…

【好书推荐】Midjourney:半途而废?还是一路坦途?

去年 AI 爆火的时候&#xff0c;也赶时髦用上了 Midjourney。平时用它生成图片&#xff0c;感觉生成的图片好看&#xff0c;比上网四处找图更省时省事&#xff0c;更合心意&#xff0c;还不用担心版权问题。 给大家看一下我随便用 Midjourney 画的神兽图。 有一次&#xff0c…

C++相关概念和易错语法(17)(适配器模式、仿函数)

1.stack和queue stack和queue的相关接口如下&#xff1a; stack queue 我们发现不管是stack还是queue&#xff0c;它们都有push和pop&#xff0c;不区分push_back和push_front&#xff0c;这是由它们的入栈特定顺序特性决定的&#xff0c;并且它们都没有迭代器&#xff0c;st…

Java继承练习(2) (2024.7.9)

手机类 package Phone20240709;public class Phone {private String brand;private String price;private static int size;public Phone() {}public Phone(String brand, String price) {this.brand brand;this.price price;}public String getBrand() {return brand;}publ…

【独家揭秘】视频号矩阵系统源码,智能多平台管理,发布效率飙升的秘密武器!

在如今这个信息爆炸的时代&#xff0c;视频内容已经成为人们获取信息和娱乐的重要方式。然而&#xff0c;对于众多内容创作者和企业来说&#xff0c;如何高效地将视频内容发布到各大平台&#xff0c;提升品牌曝光度和用户互动&#xff0c;一直是一个头疼的问题。今天&#xff0…

京东商品历史价格查询

当前资料来源于网络&#xff0c;禁止用于商用&#xff0c;仅限于学习。 下载京东APP 登录后 打开商品详情就可以看到 要获取京东商品的历史价格&#xff0c;你可以在京东网站上搜索该商品&#xff0c;并进入该商品的详情页面。然后&#xff0c;在页面中找到“商品详情”一栏&…