探讨4层代理和7层代理行为以及如何获取真实客户端IP

news2024/10/6 6:34:13

准备工作

实验环境

IP角色
192.168.1.100客户端请求IP
192.168.1.100python 启动的HTTP服务
192.168.1.102nginx服务
192.168.1.103haproxy 服务

HTTP服务

这是一个简单的HTTP服务,主要打印HTTP报文用于分析客户端IP

#!/usr/bin/env python
# coding: utf-8

import socket
from threading import Thread

# 创建socket对象
sock_srv = socket.socket()

# 绑定IP和port
sock_srv.bind(('0.0.0.0', 5001))

# 开启服务
sock_srv.listen()

# 定义一个函数, 处理来自客户端链接的处理
def socket_deal(conn: socket.socket, address: tuple):
	# 通过socket获取客户端的IP; 这里的客户端IP其实指的是TCP报文中的原始IP和原始Port
	# 就是上一个发起TCP发起的地址 
    print(address)

    # 打印HTTP的报文
    print(conn.recv(1024).decode())

    # 不做特殊处理,所有的请求均返回Hello Word
    template = """
HTTP/1.1 200 OK
Service: HTTP
Version: 1.1.2.2

<h1>hello word</h1>
    """
    conn.send(template.encode())

    # 关闭此次HTTP的请求
    conn.close()


while True:
    # 接受Client的数据请求
    conn, address = sock_srv.accept()
    Thread(target=socket_deal, args=(conn, address)).start()

Nginx报文分析

nginx 4层代理

  • 配置启动4层代理, 并请求 http://192.168.1.102 并观察 101 的请求信息
stream {
	server {
	  listen 80 ;
	  proxy_pass 192.168.1.100:5001;  		# Python的HTTP服务
	  # proxy_protocol on;					# 可选性, 4层携带真实IP
	}
}
  • 客户端请求4层转发,默认不传递客户端IP。
# print(address), 可以从socket得到客户端IP
('192.168.1.102', 52842)

# 得到HTTP的报文信息如下
GET / HTTP/1.1
Host: 192.168.1.102
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
  • 客户端请求4层转发,要求传递客户端IP。
# print(address), 可以从socket得到客户端IP
('192.168.1.102', 52848)

# 得到HTTP的报文信息如下,多了一行PROXY。其余信息不变
PROXY TCP4 192.168.1.100 192.168.1.102 55360 80
GET / HTTP/1.1
Host: 192.168.1.102
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

nginx 7层代理

  • 配置文件
server {                                                                           
    listen       80;                                                               
    server_name  localhost;                                                        
                                                                                   
                                                                                   
    location / {                                                                   
        proxy_pass http://192.168.1.100:8000/;                                                                         
        # proxy_set_header X-Forwarded-For $remote_addr;   # nginx 去掉注释请求携带客户端真实IP                                
    }                                                                              
                                                                                   
}
  • 客户端请求7层代理,默认不传递客户端IP真实IP。
# print(address), 可以从socket得到客户端IP
('192.168.1.102', 52854)

# 得到HTTP的报文信息如下.
GET / HTTP/1.0
Host: 192.168.1.100:5001
Connection: close
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
  • 客户端请求7层,要求传递客户端IP真实IP。
# print(address), 可以从socket得到客户端IP
('192.168.1.102', 52858)

# 得到HTTP的报文信息如下,多了一行PROXY。其余信息不变
GET / HTTP/1.0
Host: 192.168.1.100:5001
Connection: close
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
X-Forwarded-For: 192.168.1.100

分析NGINX获取客户端IP方法

方式修改header信息是否修改原始报文获取客户端IP方式
4层转发不带客户端IP不修改不修改服务端可以获取上一层发起请求的socket 源IP, 但不是客户端真实IP
4层转发携带客户端IP不修改原始报文前增加PROXY格式内容通过PROXY内容可以获取客户端IP
7层转发不带客户端IP不修改nginx重新封装HTTP报文服务端 socket 获取
7层转发携带客户端IPnginx 通过增加header信息传递客户端IPnginx重新封装HTTP报文通过nginx封装的报文获取XFF
  1. 7层代理会对报文进行重新封装,封装过程中可以通过增加XFF的header传递客户端IP。

  2. 4层转发不会修改报文。在不修改HTTP报文前提下,前置补充代理信息, 格式: PROXY TCP 客户端IP 代理端IP 客户端端口 代理端端口

Haproxy 代理分析

Haproxy 4层代理

  • 配置
defaults
    mode                    tcp

frontend  main *:80
    default_backend             app

backend app
    balance     roundrobin
    server  app1 192.168.1.100:5001 check # 不携带真实IP
    # server  app1 192.168.1.100:5001 send-proxy check  # 携带真实IP
  • 客户端请求4层转发,默认不要求传递客户端IP
# print(address) 获取客户端的address信息
('192.168.1.103', 56790)

# 这个信息和NGINX 4层信息一样
GET / HTTP/1.1
Host: 192.168.1.103
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
  • 客户端请求4层转发,要求传递客户端IP
# print(address) 获取客户端的address信息
('192.168.1.103', 58410)

# 与Nginx 4层带真实IP一样, 报文之前增加了PROXY信息
PROXY TCP4 192.168.1.100 192.168.1.103 57871 80
GET / HTTP/1.1
Host: 192.168.1.103
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

Haproxy 7层代理

  • 配置
defaults
    mode                    http
    option forwardfor       except 127.0.0.0/8   # 默认携带客户端IP,

frontend  main *:80
    default_backend             app

backend app
    balance     roundrobin
    server  app1 192.168.1.100:5001 check 
  • 客户端请求7层代理,默认传递客户端IP
# print(address) 获取客户端的address信息
('192.168.1.103', 53178)

# 与Nginx 7层带客户端IP一样, 报文包含X-Forwarded-For
GET /favicon.ico HTTP/1.1
Host: 192.168.1.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://192.168.1.103/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
X-Forwarded-For: 192.168.1.100
Connection: close
  • 客户端请求7层代理,注释不传递客户端IP
# print(address) 获取客户端的address信息
('192.168.1.103', 53576)

# 与Nginx 7层不传递客户端IP一样, 报文包含没有X-Forwarded-For
GET / HTTP/1.1
Host: 192.168.1.103
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

分析Haproxy获取客户端IP方法

其实和nginx一样

方式修改header信息是否修改原始报文获取客户端IP方式
4层转发不带客户端IP不修改不修改服务端可以获取上一层发起请求的socket 源IP, 但不是客户端真实IP
4层转发携带客户端IP不修改原始报文前增加PROXY格式内容通过PROXY内容可以获取客户端IP
7层转发不带客户端IP不修改nginx重新封装HTTP报文服务端 socket 获取
7层转发携带客户端IPnginx 通过增加header信息传递客户端IPnginx重新封装HTTP报文通过nginx封装的报文获取XFF

案例小结

上述操作主要是完成: Nginx和Haproxy两款服务分别完成: 4层转发和7层代理。 携带IP与不携带客户端IP配置上的区别和报文展示

转发方式传递方式特点
7层代理增加HTTP报文的header信息X-Forwarded-For, 进行传递客户端IP在原始报文进行修改
4层代理在HTTP报文前方附加一层PROXY信息, 进行传递客户端IP不修改原始报文,在HTTP报文前方附加数据

提前了解一下: NGINX中参数设定protocol。开启后可以处理 “在HTTP报文前方附加数据” 混淆的HTTP报文结构

在这里插入图片描述

附伪代码获取客户端IP

#!/usr/bin/env python
# coding: utf-8
import socket
from threading import Thread

# 创建socket对象
sock_srv = socket.socket()

# 绑定IP和port
sock_srv.bind(('0.0.0.0', 5001))

# 开启服务
sock_srv.listen()


# 简单的Response结构
def response(content, status, msg, conn):
    template = """
HTTP/1.1 %d %s
Service: HTTP
Version: 1.1.2.2
Content-Type: text/html; charset=UTF-8
Connection: close

%s  
    """ % (status, msg, content)
    return conn.send(template.encode())


# 定义一个函数, 处理来自客户端链接的处理
def socket_deal(conn: socket.socket, address: tuple):
    try:
        # 通过socket获取客户端的IP; 这里的客户端IP其实指的是TCP报文中的原始IP和原始Port
        # 就是上一个发起TCP发起的地址
        _client_ip, _client_port = address
        data = conn.recv(1024).decode()

        # 打印HTTP的报文
        _data_lines = data.splitlines()

        # 代理模式
        _proxy_type = "可能HTTP代理"

        # header 信息收集
        extend_data = ["header信息", ]
        for line in _data_lines:

            # 如果4层传递客户端IP,会得到如下信息。
            if line.startswith('PROXY'):
                # PROXY TCP4 192.168.1.100 192.168.1.102 55360 80
                _, protocol, _c_ip, _p_ip, _c_port, _p_port = line.split()
                if protocol != 'TCP4':
                    response("PROXY ERROR", 500, "PROXY_ERROR", conn)
                else:
                    _proxy_type = "TCP代理"
                    _client_ip = _c_ip
                    # 有时候报文只收到PROXY信息, 就需要第二次接收报文信息
                    if len(_data_lines) == 1:
                        socket_deal(conn, (_c_ip, _c_port))
                        return
                    # 如果一次性收完报文信息则继续处理
                    else:
                        continue

            if ":" not in line:
                # 不是K:V 形式,那不是header。 可能是post数据, 也可能是HTTP协议。 此处忽略
                continue

            # 拿到header信息
            header_key, header_value = [item.strip() for item in line.split(":", 1)]
            if header_key == 'X-Forwarded-For':
                _client_ip = header_value

            # header 信息入库
            extend_data.append(":".join((header_key, header_value)))

        content = ["真实的客户端IP可能是" + _client_ip, "<br />"]
        content.extend(extend_data)
        response("<br />".join(content), 200, 'ok', conn)
        
    except Exception as e:
        print(e)
    finally:
        # 关闭此次HTTP的请求
        conn.close()


while True:
    # 接受Client的数据请求
    conn, address = sock_srv.accept()
    Thread(target=socket_deal, args=(conn, address)).start()

实践: NGINX与HAProxy结合使用。

准备环境

IP角色标记说明
192.168.1.100客户端请求IPclient浏览器请求4层转发到后端HTTP服务
192.168.1.102NGINX实现提供4层转发NGINX-PROXY转发到104服务器
192.168.1.103Haproxy提供4层转发HAProxy4层转发到102的7层
192.168.1.104NGINX 7层服务NGINX-HTTP代表HTTP服务器。直接返回,并观察日志
  1. 启动一台NGINX HTTP服务器,扮演正常访问的网站。 代号NGINX-HTTP
  2. 另启动一台NGINX服务器,实现四层转发功能到NGINX HTTP服务器,代号NGINX-PROXY
  3. 启动一台HAProxy服务器,实现四层转发功能到NGINX HTTP服务器,代号HAProxy
  4. 在客户端分别访问NGINX-PROXY和HAProxy, 并采集NGINX-HTTP的日志
  5. 在NGINX-PROXY和HAProxy交叉请求CURL,并携带Header信息: X-FORWARDED-FOR, 并采集NGINX-HTTP的日志
  6. PROXY-PROTOCOL, 是四层转发开启携带真实IP补充协议,即: 在HTTP报文前方附加的数据。 参考文档

NGINX-HTTP服务器

  • HTTP服务主要配置
  • 因为4层转发携带了真实IP后, NGINX收到的不再是一个纯粹的HTTP报文。 所以需要在NGINX服务开启如下设置。 参考文档

http {
	# r:访问IP, 也就是代理端IP。 
	# P: PROXY-PROTOCOL的IP,也就是4层转发携带的补充报文的IP,也就是客户端IP。 
	# xff: 藏在Header中的X-Forwarded-For的IP。
	log_format  proxy_protocol_log  'r: $remote_addr p: $proxy_protocol_addr xff: $http_x_forwarded_for';

 	server {
 		access_log logs/proxy_protocol_access.log proxy_protocol_log;	# 观察IP: 访问IP,代理IP,XFF
 		error_log logs/proxy_protocol_error.log

		listen       80 ;               		# 接收HTTP报文走80端口                                        
	 	listen       8000 proxy_protocol;     	# PROXY PROTOCOL 走8000端口,PROTOCOL 是通过四层转发获取真实IP的补充协议               
	 	server_name  localhost;   

	 	location / {
	 		root html;
	 		index index.html;
	 	}
	}
}

NGINX-PROXY服务器

关键配置

stream {
	server {
	  listen 80 ;
	  proxy_protocol on; 	# 需要开启使用PROXY PROTOCOL协议。
	  proxy_pass 192.168.1.104:8000;
	}
}

浏览器访问, NGINX-HTTP(192.168.1.104)输出日志信息

tail logs/proxy_protocol_access.log
r: 192.168.1.102 p: 192.168.1.100 xff: -

CURL访问,NGINX-HTTP(192.168.1.104)输出日志信息

tail logs/proxy_protocol_access.log
r: 192.168.1.102 p: 192.168.1.103 xff: 192.168.1.199

HAProxy服务器

关键配置

defaults
    mode  tcp

backend app
    balance     roundrobin
    server  app1 192.168.1.104:8000 send-proxy  	# send-proxy 开启支持PROXY-PROTOCOL

浏览器访问, NGINX-HTTP(192.168.1.104)输出日志信息

tail -f logs/proxy_protocol_access.log
r: 192.168.1.103 p: 192.168.1.100 xff: -

CURL访问,NGINX-HTTP(192.168.1.104)输出日志信息

tail -f logs/proxy_protocol_access.log
r: 192.168.1.103 p: 192.168.1.102 xff: 192.168.1.199

再次小结

我们尝试结合常见配置结构进行验证。 可以初步发现

  1. 4层转发携带客户端IP是需要使用PROPXY-PROTOCOL协议支持。客户端IP会补充在这个协议内
  2. 作为4层转发端,因为4层转发不修改报文,所以在HTTP报文前添加PROPXY-PROTOCOL信息。
    • 4层转发服务器需要开启 protocol 支持发送PROXY-PROTOCOL+HTTP的混淆报文结构
    • 4层目标服务器需要开启 protocol 支持接收PROXY-PROTOCOL+HTTP的混淆报文结构
  3. 使用补充PROXY-PROTOCL后,HTTP的报文不在是一个纯粹的报文结构,所以作为服务网端NGINX开启了两种模式
    • listen 80; 支持处理普通HTTP请求,
    • listen 80 protocol; 支持处理PROXY-PROTOCOL + HTTP报文的形式。这也是四层代理携带IP的特有形式
  4. 在选择HTTP服务器时,需要考虑HTTP服务是否支持PROXY-PROTOCOL。

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

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

相关文章

【c++刷题笔记-数组】day29:452. 用最少数量的箭引爆气球、 435. 无重叠区间 、 763.划分字母区间

452. 用最少数量的箭引爆气球 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;先按照左边界排序&#xff0c;当前的左边界大于前一个的右边界的时候&#xff0c;表示没有覆盖所以需要一根箭&#xff0c;反之则要更新为最小的右边界 重点&#xff1a;是区间覆盖问题…

FMEA在大型光伏电站安全生产管理中的应用

一、FMEA概述 FMEA&#xff08;Failure Modes and Effects Analysis&#xff09;即失效模式和影响分析&#xff0c;是一种用于识别和分析产品或过程中潜在故障模式及其影响的方法。它通过对产品或过程中可能出现的故障模式进行系统性地梳理和分析&#xff0c;评估其可能的影响…

Day59 动态规划part12

LC115不同的子序列&#xff08;未掌握&#xff09; 递推公式与LC392类似&#xff0c;但是初始化略有不同 LC392的dp数组含义为相同字符个数而本体的dp数组含义为出现的次数&#xff0c;因此dp[i][0]1 两种情况 s[i-1]t[j-1] dp[i][j] dp[i-1][j-1]dp[i][j] dp[i-1][j] s[…

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日&#xff0c;阿里通义实验室发布开源语音大模型项目FunAudioLLM&#xff0c;而且一次包含两个模型&#xff1a;SenseVoice和CosyVoice。 CosyVoice专注自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;支持中英日粤韩5种语言的生成&#xff0c;效果显著优于…

JAVA集合框架、CAS、AQS

目录 一、java 的集合框架有哪些? 二、说-下 ArrayList 和 LinkedList? 三、HashSet和TreeSet的区别? 四、HashMap 的数据结构是什么? 五、CAS机制 六、AQS理解 一、java 的集合框架有哪些? Collection 是 Java 集合框架中的一个根接口&#xff0c;位于 java.util 包中。它…

那些年背过的面试题——MySQL篇

本文是技术人面试系列 MySQL 篇&#xff0c;面试中关于 MySQL 都需要了解哪些基础&#xff1f;一文带你详细了解&#xff0c;欢迎收藏&#xff01; WhyMysql&#xff1f; NoSQL 数据库四大家族 列存储 Hbase K-V 存储 Redis 图像存储 Neo4j 文档存储 MongoDB 云存储 OSS …

RabbitMQ中常用的三种交换机【Fanout、Direct、Topic】

目录 1、引入 2、Fanout交换机 案例&#xff1a;利用SpringAMQP演示Fanout交换机的使用 3、Direct交换机 案例&#xff1a;利用SpringAMQP演示Direct交换机的使用 4、Topic交换机 案例&#xff1a;利用SpringAMQP演示Topic交换机的使用 1、引入 真实的生产环境都会经过e…

[240707] X-CMD v0.3.14: cb gh fjo zig 模块增强;新增 lsio 和 pixi 模块

目录 X-CMD 发布 v0.3.14✨ advise&#xff1a;Bash 环境下自动补全时&#xff0c;提供命令的描述信息✨ cb:支持下载指定版本的附件资源✨ gh:支持下载指定版本的附件资源✨ fjo:支持下载指定版本的附件资源✨ zig&#xff1a;新增 pm 和 zon 子命令✨ lsio&#xff1a;用于查…

Maven一键配置阿里云远程仓库,让你的项目依赖飞起来!

文章目录 引言一、为什么选择阿里云Maven仓库&#xff1f;二、如何设置Maven阿里云远程仓库&#xff1f;三、使用阿里云Maven仓库的注意事项总结 引言 在软件开发的世界里&#xff0c;Maven无疑是一个强大的项目管理工具&#xff0c;它能够帮助我们自动化构建、依赖管理和项目…

并发处理 优先图和多重图

优先图(Precedence Graph)视图可串性多重图(Polygraph) 优先图(Precedence Graph) 优先图用于冲突可串性的判断。 优先图结构&#xff1a; 结点 (Node)&#xff1a;事务&#xff1b;有向边 (Arc): Ti → Tj &#xff0c;满足 Ti <s Tj&#xff1b; 存在Ti中的操作A1和Tj…

43、nginx的优化、防盗链、重定向、代理

nginx的优化、防盗链、重定向、代理 一、nginx的优化 1.1、隐藏版本号 server_tokens off;隐藏版本号 [roottest1 conf]# vim nginx.confserver_tokens off;[roottest1 conf]# nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok ngin…

机器学习训练之使用静态图加速

前言 MindSpore有两种运行模式&#xff1a;动态图模式和静态图模式。默认情况下是动态图模式&#xff0c;也可以手工切换为静态图模式。 动态图模式 动态图的特点是计算图的构建和计算同时发生&#xff0c;符合Python的解释执行方式。在调试模型时较为方便&#xff0c;能够实…

科大讯飞-群聊对话角色要素提取:不微调范式模拟官网评分

不微调范式模拟官网评分 step1: 模型api配置及加载测试step2: 数据加载与数据分析&#xff1a;测试集分析:step3: prompt设计:step4 :大模型推理&#xff1a;step 5: 结果评分测试&#xff1a;评分细则&#xff1a;评估指标 参考&#xff1a; 比赛说明&#xff1a; #AI夏令营 #…

从打印到监测:纳米生物墨水助力3D生物打印与组织监测平台?

从打印到监测&#xff1a;纳米生物墨水助力3D生物打印与组织监测平台&#xff1f; 在 3D 组织工程中&#xff0c;纳米生物墨水是将纳米材料与 ECM 水凝胶结合&#xff0c;以提高其打印性和功能性的重要策略。纳米生物墨水可以增强水凝胶的机械性能、导电性、生物活性&#xff…

【Transformer】transformer模型结构学习笔记

文章目录 1. transformer架构2. transformer子层解析3. transformer注意力机制4. transformer部分释疑 图1 transformer模型架构 图2 transformer主要模块简介 图3 encoder-decoder示意图N6 图4 encoder-decoder子层示意图 1. transformer架构 encoder-decoder框架是一种处理NL…

卷积神经网络基础篇

文章目录 1、卷积层1.1、激活函数1.3、sigmoid1.4、Tanh1.5、ReLU1.6、Leaky ReLU1.7、误差计算 2、池化层3、全连接层4、CNN训练 参考链接1 参考链接2 1、卷积层 卷积层&#xff08;Convolutional layer&#xff09;&#xff0c;这一层就是卷积神经网络最重要的一个层次&…

数据库的学习(4)

一、题目 1、创建数据表qrade: CREATE TABLE grade(id INT NOT NULL,sex CHAR(1),firstname VARCHAR(20)NOT NULL,lastname VARCHAR(20)NOT NULL,english FLOAT,math FLOAT,chinese FLOAT ); 2、向数据表grade中插入几条数据: (3,mAllenwiiliam,88.0,92.0 95.0), (4,m,George&…

java版企业工程管理系统源码:全方位的项目管理解决方案

工程管理系统是一款专注于建设工程项目全生命周期管理的软件。它覆盖了项目从策划、设计、施工到竣工的每一个阶段&#xff0c;提供全方位的管理功能。系统采用模块化设计&#xff0c;包括系统管理、系统设置、项目管理、合同管理、预警管理、竣工管理、质量管理、统计报表和工…

centos7.9 rpm包安装mysql8.2.0数据库、root设置客户端登录、配置并发、表名大小写敏感、启动重启指令等记录

centos安装mysql8数据库,下载的是rpm-bundle.tar包,这样可以在内网环境离线安装,工作中医院的服务器很多也是内网的,所以这里记录下rpm-bundle.tar包安装的步骤。 lscpu 查看处理器是x86还是arm 下载对应的版本 bundle tar包 ((mysql-8.2.0-1.el7.x86_64.rpm-bundle.tar))…

打造属于你的私人云盘:在 OrangePi AIpro 上搭建个人云盘

随着数字化时代的到来&#xff0c;数据的存储和管理变得愈发重要。相比于公共云存储服务&#xff0c;搭建一个属于自己的个人云盘不仅能够更好地保护隐私&#xff0c;还可以更灵活地管理数据。 近期刚好收到了一个 香橙派 AIpro 的开发板&#xff0c;借此机会用来搭建一个属于…