皮皮网
皮皮网

【laysns仿 导航源码】【狼行天下源码】【什么源码有价值】haproxy 源码 socket

时间:2024-12-27 21:30:43 来源:万千源码

1.OpenStack虚拟机如何获取metadata
2.使用命令行启停HAProxy的Backend
3.HAProxy 的 ACLs 详解
4.超级NB的黑科技,实现socket进程间迁移!

haproxy 源码 socket

OpenStack虚拟机如何获取metadata

       OpenStack虚拟机初始化配置主要依赖cloud-init,其通过Metadata服务获取配置信息。Metadata服务的配置包括Nova和Neutron的设置,如将metadata服务与nova-api合并,laysns仿 导航源码以及选择通过dhcp-agent转发。访问Metadata服务的地址为...,这是个保留的IPv4 Link Local Address,用于直连网络的内部通信。

       OpenStack虚拟机通过访问...获取诸如uuid、name等信息,这个过程涉及三次转发:首先到DHCP地址,再由haproxy转发到一个本地socket文件,狼行天下源码最后neutron-metadata-agent根据network id和IP信息确定虚拟机uuid。Nova Metadata服务通过uuid查询metadata信息,并在转发前验证secret以确保安全性。

       在虚拟机外部获取metadata,可以通过Python脚本生成secret并利用它调用nova-api-metadata服务。整个流程涉及Nova Metadata服务、DHCP地址转发、本地socket文件处理和secret验证。

使用命令行启停HAProxy的Backend

        HAProxy自带监控页面,需要在HAProxy使用的配置文件haproxy.cfg中添加配置项进行开启,重启HAProxy服务后生效。

        添加的配置大致如下:

        浏览器地址栏输入 t <integer>

req_rdp_cookie_cnt(name) <integer>

        远程桌面协议相关

        req_ssl_ver <decimal>

        如果在请求缓存中的数据,看起来像 SSL 协议数据,而且协议版本在指定的范围内,返回 ture。

        支持 SSLv2 hello messages 和 SSLv3 messages。

        此测试意在进行严格限制,尽量避免被轻易地欺骗。

        In particular, it waits for as many bytes as announced in the

        message header if this header looks valid (bound to the buffer size)

        注意,TLSv1 协议将被称为 SSL version 3.1。

        用于 “TCP 请求内容检查”

        wait_end

        等待分析周期结束,返回 true。

        一般与内容分析联合使用,避免过早返回一个错误的结论。

        也可用于延迟某些动作,比如拒绝某些指定的IP地址的动作。

        因为它要么停止规则检查,要么立即返回 true,所以建议在一条规则的最后使用这个 acl。

        注意,默认的 ACL "WAIT_END" 总是可用的,不需要预先声明。

        本测试用于 “TCP 请求内容检查”

        示例:

        第三部分的测试区域,是七层测试。要求对 HTTP 请求进行完全的解析之后进行。

        因为请求和响应都被建立了索引,所以虽然相比四层匹配要求更多的 CPU 资源,但也不会太多。

        hdr <string>

hdr(header) <string>

        hdr* 匹配所有 headers,hdr*(header) 匹配指定的 header,注意括号里面不能有空格。

        指定首部时,其名称不区分大小写;

        The header matching complies with RFC, and treats all values delimited by commas as separate headers.

        对于响应首部,使用 shdr();

        示例,检查是否设置了 "connection: close" :

        hdr_beg <string>

hdr_beg(header) <string>

        任何一个 header 的值是以 string 起始的,返回 true

        对于响应首部,使用 shdr_beg();

        hdr_cnt <integer>

hdr_cnt(header) <integer>

        如果指定的 header 出现的次数在指定范围内,或匹配指定的值,返回 true;

        一行 header 语句如果包含多个值,将被多次计数;

        用于检查指定 header 的是否存在,是否被滥用;

        通过拒绝含有多个指定 header 的请求,可阻挡 request smuggling attacks;

        对于响应首部,使用 shdr_cnt();

        hdr_dir <string>

hdr_dir(header) <string>

        用于文件名或目录名匹配,当某个 header 包含被 / 分隔的 string,返回 true;

        可与 Referer 联合使用;

        对于响应首部,使用 shdr_dir();

        hdr_dom <string>

hdr_dom(header) <string>

        用于域名匹配,可与 Host header 一起使用;当某个 header 包含被 . 分隔的 string,返回 true;

        对于响应首部,使用 shdr_dom();

        hdr_end <string>

hdr_end(header) <string>

        当任何一个 header 的值是以 string 结束的,返回 true

        对于响应首部,使用 shdr_end();

        hdr_ip <ip_address>

hdr_ip(header) <ip_address>

        当某个 header 的值包含匹配 <ip_address> 的值,返回 true;

        通常与 X-Forwarded-For or X-Client-IP 一起使用;

        对于响应首部,使用 shdr_ip();

        hdr_len <integer>

hdr_len(<header>) <integer>

        至少有一个 header 的 length 与指定的值或者范围匹配时,返回 true;

        对于响应首部,使用 shdr_len();

        hdr_reg <regex>

hdr_reg(header) <regex>

        有一个 header 与正则表达式匹配时,返回 true,可在任何时候使用;

        注意,正则匹配比其他匹配更慢;

        对于响应首部,使用 shdr_reg();

        hdr_sub <string>

hdr_sub(header) <string>

        有一个 header 包含其中一个 string 时,返回 true;

        对于响应首部,使用 shdr_sub();

        hdr_val <integer>

hdr_val(header) <integer>

        有一个 header 起始的数字,与指定值或范围匹配;可用于限制 content-length,只接受合理长度的请求;

        对于响应首部,使用 shdr_val();

        http_auth(userlist)

http_auth_group(userlist) <group> [<group>]*

        从客户端收到的认证信息与 userlist 中记录的匹配时,返回 true;

        目前只支持 http basic auth;

        http_first_req

        如果处理的请求是连接的第一个请求,返回 true;

        method <string>

        用于检查 HTTP 请求的方法,匹配时,返回 true;

        path <string>

        请求中的 path 部分(以 / 起始,到 ? 为止的部分),与某个 string 相等时,返回 true;

        可用于匹配某个文件,比如:/favicon.ico

        path_beg <string>

        当 path 以某个 string 为起始,返回 true;可用于发送某些目录名到 alternative backend;

        path_dir <string>

        当 path 中包含以 / 分隔的 string 时,返回 true;可用于匹配文件名或目录名;

        path_dom <string>

        当 path 中包含以 . 分隔的 string 时,返回 true;可用于域名匹配;

        path_end <string>

        当 path 以某个 string 为结束时,返回 true;可用于控制文件扩展名;

        path_len <integer>

        当 path 的长度与指定值或范围匹配时,返回 true;可用于检测 abusive requests;

        path_reg <regex>

        当 path 与正则表达式匹配时,返回 true;

        path_sub <string>

        当 path 包含某个 string 时,返回 true;可用于检测 path 中的指定模式,比如 “../”;

        req_ver <string>

        用于检查 HTTP 请求的版本,比如 1.0;

        status <integer>

        用于检查 HTTP response 的状态码,比如 ;

        可根据状态码做一定的动作,比如,如果 response 的状态码不是 3xx,则删除 Location header;

        url <string>

        应用于请求中的整个 URL;真正的用处是匹配 *,已有一个预定义的 ACL: HTTP_URL_STAR;

        url_beg <string>

        当 URL 以某个 string 起始时,返回 true;可用于检查是否以 / 或者某个协议的 scheme 起始;

        url_dir <string>

        如果 URL 中包含以 / 分隔的 string,返回 true;用于文件名和目录名匹配;

        url_dom <string>

        如果 URL 中包含以 . 分隔的 string,返回 true;用于域名匹配;

        url_end <string>

        当 URL 以某个 string 结束时,返回 true;用处很少;

        url_ip <ip_address>

        用于检查 HTTP 请求中,绝对 URI 中所指定的 IP 地址;可用于根据 IP 地址做资源的访问限制;

        跟 http_proxy 一起用时可发挥作用;

        url_len <integer>

        当 URL 的长度与指定值或范围匹配时,返回 true;可用于检测 abusive requests;

        url_port <integer>

        用于检查 HTTP 请求中,绝对 URI 中所指定的 PORT 地址;可用于根据 PORT 地址做资源的访问限制;

        跟 http_proxy 一起用时可发挥作用;

        注意,如果请求中没有指定端口,则表示端口为 ;

        url_reg <regex>

        当 URL 与正则表达式匹配时,返回 true;

        url_sub <string>

        当 URL 包含某个 string 时,返回 true;可用于检查 query string 中的某些 pattern;

        预定义的 ACLs 不需要声明,可以直接使用。它们的命名都是大写字母。

        有些 actions 只在满足了有效的条件时才能执行;条件是 ACLs 的逻辑组合;

        有三个可用的逻辑运算符:

        一个条件的构成:

        actions 配合条件:

        例如,构造一个条件,希望阻挡满足条件 HTTP 请求,满足如下条件之一时,拒绝该请求:

        规则是:

        例2.

        建立 url_static 测试,当 path 以 /static、/images、/img、/css 起始,或者以 .gif、.png、.jpg、.css、.js 结尾,返回 true;

        建立 host_www 测试,当请求的 Host 首部字段以 www 起始,返回 true,忽略大小写;

        建立 host_static 测试,当请求的 Host 首部字段以 img. video. download. ftp. 之一为起始,返回 true,忽略大小写;

        满足 host_static 测试,或者 host_www AND url_static 测试的请求,转发给 static backend;

        只满足 host_www 测试的请求,转发 www backend;

        HAProxy 支持使用匿名的 ACLs;不需要事先声明;它们必须被 { ACLs } 括起来,注意空格;例如:

        一般而言,不建议使用匿名的 ACL,因为更容易出现错误;

        只有对于简单 ACLs,比如匹配一个 src IP地址,这时使用匿名更容易阅读:

        The stickiness features relies on pattern extraction in the request and

        response. Sometimes the data needs to be converted first before being stored,

        for instance converted from ASCII to IP or upper case to lower case.

        All these operations of data extraction and conversion are defined as

        "pattern extraction rules". A pattern rule always has the same format. It

        begins with a single pattern fetch word, potentially followed by a list of

        arguments within parenthesis then an optional list of transformations. As

        much as possible, the pattern fetch functions use the same name as their

        equivalent used in ACLs.

        The list of currently supported pattern fetch functions is the following :

        src This is the source IPv4 address of the client of the session.

        It is of type IP and only works with such tables.

        dst This is the destination IPv4 address of the session on the

        client side, which is the address the client connected to.

        It can be useful when running in transparent mode. It is of

        type IP and only works with such tables.

        dst_port This is the destination TCP port of the session on the client

        side, which is the port the client connected to. This might be

        used when running in transparent mode or when assigning dynamic

        ports to some clients for a whole application session. It is of

        type integer and only works with such tables.

        hdr(name) This extracts the last occurrence of header <name> in an HTTP

        request and converts it to an IP address. This IP address is

        then used to match the table. A typical use is with the

        x-forwarded-for header.

        The currently available list of transformations include :

        lower Convert a string pattern to lower case. This can only be placed

        after a string pattern fetch function or after a conversion

        function returning a string type. The result is of type string.

        upper Convert a string pattern to upper case. This can only be placed

        after a string pattern fetch function or after a conversion

        function returning a string type. The result is of type string.

        ipmask(mask) Apply a mask to an IPv4 address, and use the result for lookups

        and storage. This can be used to make all hosts within a

        certain mask to share the same table entries and as such use

        the same server. The mask can be passed in dotted form (eg:

        ...0) or in CIDR form (eg: ).

超级NB的黑科技,实现socket进程间迁移!

       今天我们将探讨一项令人瞩目的技术:实现socket句柄在进程间的迁移。在服务器领域,我们经常需要管理大量的什么源码有价值server实例。这些实例需要处理数以万计的连接和繁重的网络请求。如果能轻而易举地控制这些连接,像操作乐高积木一样,那么在软件升级时,我们就可以先启动一个新版本的进程,然后将老进程的socket逐个转移到新进程中,实现无缝升级。这项技术,Facebook已成功实践,被称为SocketTakeover。虽然这项技术很有用,但在搜索引擎中却难以找到相关资料。也许大家都在忙于研究茴香豆的全息视频源码大全茴字怎么写,无暇他顾。今天,就由我为大家揭开这项技术的神秘面纱,让你的吹牛资本更上一层楼。这项功能,是基于Linux底层系统调用函数sendmsg()和recvmsg()实现的。

       首先,我们需要了解c语言网络编程的基础。通常,我们会通过listen函数注册监听地址,然后使用accept函数接收新连接。例如:

       ```c

       int listen_fd = socket(addr->ss_family, SOCK_STREAM, 0);

       ...

       bind(listen_fd, (struct sockaddr*)addr, addrlen);

       ...

       int accept_fd = accept(fd, (struct sockaddr*)&addr, &addrlen);

       ```

       我们的目标,是指标导入源码大全将listen_fd从一个进程传递到另一个进程。这需要一个通道,而在Linux上,那就是Unix Domain Sockets(UDS)。

       UDS在Linux上表现为一个文件,它允许进程通过这个文件进行数据传输,而无需经过网卡等物理设备,因此速度极快。今天,我们不关注它的速度,而是关注它的实用性。通过bind函数,我们可以在UDS文件上接收连接,就像在端口上接收连接一样。

       ```c

       struct sockaddr_un addr;

       char*path = "/tmp/xjjdog.sock";

       int fd;

       fd = socket(AF_UNIX, SOCK_STREAM, 0);

       memset(&addr, 0, sizeof(struct sockaddr_un));

       addr.sun_family = AF_UNIX;

       strncpy(addr.sun_path, path, strlen(path));

       addrlen = sizeof(addr.sun_family) + strlen(path);

       err = bind(fd, (struct sockaddr*)&addr, addrlen);

       ...

       accept_fd = accept(fd, (struct sockaddr*)&addr, &addrlen);

       ```

       其他进程,现在可以通过端口或UDS文件连接到我们的服务。

       接下来,我们来看迁移的过程。关键在于sendmsg函数的第二个参数——msghdr结构体。msghdr结构体包含了一些iov(输入/输出缓冲区)和控制信息。其中,控制信息可以通过CMSG_FIRSTHDR宏获取,它指向cmsghdr结构体。cmsghdr结构体中有一个cmsg_type成员,用于指定控制信息的类型。在这里,我们关注SCM_RIGHTS类型,它允许我们从一个进程发送文件句柄到另一个进程。

       ```c

       struct msghdr msg;

       ...

       struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);

       cmsg->cmsg_level = SOL_SOCKET;

       cmsg->cmsg_type = SCM_RIGHTS;

       // 设置cmsg_data为socketfd列表

       int* fds = (int*)CMSG_DATA(cmsg);

       ```

       通过sendmsg函数,socket句柄就被发送到另一个进程了。

       接收方,则需要使用recvmsg函数,并解析cmsghdr结构体,从cmsg_data中获取句柄列表。实际上,socket句柄在进程中只是一个引用,真正的句柄在内核中。迁移,不过是将一个引用从内核中移除,然后添加到另一个进程中。

       对于普通fd,我们需要调用与原始连接到来时相同的代码逻辑。因此,迁移过程包括:迁移listener fd到新进程并开始监听,迁移大量的socket连接,并逐步在新进程中还原它们。完成后,老进程就可以安全地关闭了。

       这是一项具有革命性的技术,已经在一些主流应用中得到应用。例如,HAProxy用于4层网络的负载均衡;Envoy和Istio默认的数据平面软件,也使用类似技术完成热重启。在service mesh的推进过程中,proxy的替换也会使用这种技术,如SOFA。虽然golang和C语言因为API暴露较好,实现起来较为容易,但在Java中,由于缺少这种为Linux定制的API,实现起来就有不少困难。这种技术非常适合无状态的proxy服务,如果有状态的服务尝试使用,可能会有安全风险,但也可以尝试应用在一些中间件上。无论如何,这种技术的出现,肯定会令windowsserver用户羡慕不已。

更多内容请点击【探索】专栏