来自 Python 的 AWS 网络负载均衡器后面的客户端 IP

2024-03-15

当在网络负载均衡器后面运行套接字服务器时,实例由 IP 指定,...

server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP)
server_sock.setblocking(False)
server_sock.bind(('', port))
server_sock.listen(socket.IPPROTO_TCP)

loop = asyncio.get_event_loop()
sock, adddress = await loop.sock_accept(server_sock)

... 然后...

print(adddress)

打印网络负载均衡器本身的私有 IP。

如何确定原始客户端IP?


您可以启用代理协议V2 https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#proxy-protocol,然后编写一个函数来解析代理协议标头[在传入数据之前发送]...

import asyncio
import collections
import socket
import struct


PP_V2_SIGNATURE = b'\r\n\r\n\x00\r\nQUIT\n'

PP_V2_COMMANDS = {
    b'\x00': 'LOCAL',
    b'\x01': 'PROXY',
}

PP_V2_VERSIONS = {
    b'\x02': '2',
}

PP_V2_ADDRESS_FAMILIES = {
    b'\x00': 'AF_UNSPEC',
    b'\x01': 'AF_INET',
    b'\x02': 'AF_INET6',
    b'\x03': 'AF_UNIX',
}

PP_V2_PROTOCOLS = {
    b'\x00': 'UNSPEC',
    b'\x01': 'STREAM',
    b'\x02': 'DGRAM',
}

PP_V2_ADDRESS_FORMATS = {
    'AF_INET': '4B4BHH',
    'AF_INET6': '16B16BHH',
    'AF_UNIX': '108B108B',
}

ProxyProtocolV2Header = collections.namedtuple('ProxyProtocolV2Header', [
    'version',
    'command',
    'protocol',
    'address_family',
    'address',
])

ProxyProtocolIpAddress = collections.namedtuple('ProxyProtocolIpAddress', [
    'source_ip',
    'source_port',
    'dest_ip',
    'dest_port',
])


async def proxy_protocol_header_recv(loop, sock):
    # The header, itself has a header
    header_format = '>12sccH'
    header_length = 16

    header_raw = await recv_num_bytes(loop, sock, header_length)
    header_unpacked = struct.unpack(header_format, header_raw)

    signature = header_unpacked[0]
    version_and_command = header_unpacked[1][0]
    protocol_and_address_family = header_unpacked[2][0]
    address_length = header_unpacked[3]

    if signature != PP_V2_SIGNATURE:
        raise Exception('Incorrect proxy protocol signature')

    version = PP_V2_VERSIONS[bytes([version_and_command >> 4])]
    command = PP_V2_COMMANDS[bytes([version_and_command & 0x0f])]

    protocol = PP_V2_PROTOCOLS[bytes([protocol_and_address_family & 0x0f])]
    address_family = PP_V2_ADDRESS_FAMILIES[bytes([protocol_and_address_family >> 4])]

    address_raw = await recv_num_bytes(loop, sock, address_length)

    address_format = PP_V2_ADDRESS_FORMATS[address_family]
    address = struct.unpack(address_format, address_raw[:struct.calcsize(address_format)])

    return ProxyProtocolV2Header(
        version=version,
        command=command,
        protocol=protocol,
        address_family=address_family,
        # For IPV6/Unix, you'll need to do something else
        address=ProxyProtocolIpAddress(
            source_ip='.'.join(str(part) for part in address[:4]),
            source_port=address[8],
            dest_ip='.'.join(str(part) for part in address[4:8]),
            dest_port=address[9],
        ) if address_family == 'AF_INET' else None,
    )

async def recv_num_bytes(loop, sock, num_bytes):
    incoming_buf = bytearray(num_bytes)
    incoming = memoryview(incoming_buf)
    bytes_in_total = 0

    while bytes_in_total != num_bytes:
        bytes_just_in = await loop.sock_recv_into(sock, incoming[bytes_in_total:])
        if bytes_just_in == 0:
            raise Exception('Socket closed')
        bytes_in_total += bytes_just_in

    return incoming_buf

...您可以将其用作,例如:

async def main(loop):

    port = 5023

    server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP)
    server_sock.setblocking(False)
    server_sock.bind(('', port))
    server_sock.listen(socket.IPPROTO_TCP)

    while True:
        print('Waiting for connection')
        sock, adddress = await loop.sock_accept(server_sock)
        header = await proxy_protocol_header_recv(loop, sock)
        print(header.address.source_ip)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

来自 Python 的 AWS 网络负载均衡器后面的客户端 IP 的相关文章

  • AWS ios SDK - 弹性转码器作业的 http post 请求

    查看AWS弹性转码器 有几个问题 对于我的用例来说 首先使用转码器是否具有重要价值 我正在制作一个允许用户选择视频的 ios 应用程序 当他们这样做时 我会将其上传到 S3 存储桶 据我了解 我应该使用弹性转码器对这些视频进行转码 并将它们
  • 从数据帧字典中获取单独的数据帧 Python

    我有一本字典d充满了数据帧的集合 key type size value gm1 dataframe mxn gm2 dataframe mxN gm10 dataframe nxM 我想使用它们来一一输出这些数据帧keys作为新数据框的名
  • Python IF 语句到单行

    是否可以将这段代码放在一行中 if x 0 a j sum elif x 1 b j sum e e D 这不是一个仅用于演示目的的工作示例 a j sum if x 0 else b j sum 如果您有 Python 3 8 或更高版本
  • 更新AWS S3过期时间

    我想知道如何延长密钥的有效期 我指的不是访问对象的签名 URL 而是密钥本身 我将 AWS 设置为存储桶中的所有对象应在 90 天后过期的规则 在大多数情况下 这就是我希望发生的事情 有时我需要将单个密钥的使用寿命最多再延长 90 天 事实
  • 如何获取AWS ec2中区域的可用容量?

    AWS 终止了我的运行位置 并出现错误 实例终止容量超额订阅 有没有办法查看不同 ec2 区域中实例类型的可用容量 这样我就可以在更 可用 的区域创建我的新位置 查看 现货实例历史记录 这不会告诉您未来 但会给您迄今为止的良好指示 此链接将
  • 默认可变参数的惯用方式

    在 python 中 如果直接将可变类型设置为默认参数 则会出现众所周知的边缘情况 def foo x return x y foo y append 1 print foo 通常的解决方法是将参数默认为None然后将其放入体内 然而 有
  • 多行 x 刻度标签

    我正在尝试制作类似于此 Excel 示例的图 我想知道 x 刻度标签上是否有第二层 例如 5 年统计摘要 我知道我可以使用制作多行刻度标签 n但我希望能够独立地转换这两个级别 这很接近 fig plt figure figsize 8 4
  • 扩展策略中的AWS ASG冷却期和预热期有什么区别?

    AWS ASG 冷却期 当我想要更新自动扩展组时可以编辑该冷却期 和扩展策略中的预热期之间有什么区别 冷却时间可以防止失控的缩放事件 如果您的系统在 CPU 上运行较高 并且您的自动扩展规则添加了一个实例 则该实例将需要 5 分钟左右的时间
  • 导入错误:无法导入名称“IntEnum”

    我正在尝试安装upstox 这是一个用于连接市场数据的 Python API 我无法在Python3 5上安装它 我的配置是Python 3 5 3 v3 5 3 1880cb95a742 Jan 16 2017 15 51 26 MSC
  • 基于 SQS 队列大小的自动缩放

    我已将这些命令组合在一起 以根据 SQS 队列大小自动缩放 EC2 实例 我已运行所有命令 我的队列有 10 条消息 但尚未启动单个实例 我想弄清楚我的 cloudwatch 警报正在侦听哪个 SQS 队列 此外 我们还感谢任何有助于识别问
  • pytest 在导入时找不到模块,但代码运行良好

    目标是为使用 Cython 的 Python3 项目使用 pytest 单元测试框架 这不是即插即用的事情 因为默认情况下 pytest 无法导入 Cython 模块 也就是说 从 Cython pyx 模块导入时出现以下错误 在我的例子中
  • 带括号的上下文管理器

    我试图了解新的新内容带括号的上下文管理器Python 3 10 中的功能 新功能中的顶部项目here https docs python org 3 10 whatsnew 3 10 html 我的测试示例是尝试编写 with open f
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • 关于 S3 文件传输的权限

    我正在使用 S3TransferManager Sample 进行测试 我创建了Cognito并设置了IAM并最后更改了constants swift文件 我上传没有问题 但下载失败 错误信息是 下载失败 错误域 com amazonaws
  • Rails 应用程序中的持久 TCP 连接

    我有一个在服务器上运行的第三方应用程序 它对客户端进行身份验证并返回响应 我的问题是 对于我收到 Rails 应用程序的每个请求 我都需要建立 TCP 连接并获取数据 是否可以有一个持久连接 以便我可以减少建立连接的开销 我希望你使用的是
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 使用 ecs-cli 在 AWS 上部署 docker 时遇到问题

    我在 ECS 上有一个存储库 已使用 ecs cli 创建了一个集群 ecs cli configure region us west 2 profile
  • 如何使用python读取最后一行的特定位置

    我有一个太大的 txt 文件 并且有几行类似的行 如下所示 字1 字2 字3 字4 553 75 我对位置 4 值 感兴趣 即最后一行 553 75 我的文件文本 word1 word2 word3 word4 553 20 word1 w
  • Erlang get_tcp:recv数据长度

    I user gen tcp recv Socket 0 用于数据接收 但我只能接收1次1418字节 我怎样才能收到发送的数据量 in gen tcp recv Socket 0 您正在询问内核 给我接收缓冲区中现在可用的所有数据 不过 内
  • 如何将同步函数包装在异步协程中?

    我在用着aiohttp https github com aio libs aiohttp构建一个 API 服务器 将 TCP 请求发送到单独的服务器 发送 TCP 请求的模块是同步的 对于我来说是一个黑匣子 所以我的问题是这些请求阻塞了整

随机推荐