首页 > 编程语言 >为什么我的 Nodejs 的http 服务接收到的IP地址前面会有::ffff:?

为什么我的 Nodejs 的http 服务接收到的IP地址前面会有::ffff:?

时间:2024-07-10 11:19:41浏览次数:15  
标签:socket Nodejs sock IP地址 ffff ipv4 ipv6 监听 addr

Hello World

今天介绍一个比较绕口的技术。

故事的首先要从测试同学提的一个 BUG 开始

Untitled

为什么一个ipv4 地址前面会有::ffff:呢?是不是你的程序写错了呢。那我们来深究一下这个是什么东西。

这种地址叫 ipv4 mapped ipv6。为什么会有这么奇怪的东西呢,与 ipv6 部署有关。

我们知道,ipb6 的地址空间范围非常大。ipv6 改动不光涉及到网络层,例如配置 ipv6 的路由协议,还有应用层的调整,例如程序从 ipv4 监听改成 ipv6 监听。但是这个改动的成本巨大,又要涉及到代码的调整,又要涉及到地址处理的问题,例如是否监听多协议等等等,于是有人发明了 ipv6 dual stack mode 技术。通俗来讲就是

  • 程序只需要监听 ipv6,如果不做特殊设置(IPV6_ONLY) 那么socket 同时附带同时也监听 ipv4。并且 ipv4 接受到的请求,自动转换为 ipv6 的格式交给应用层处理

下面我们写一个python 的小程序来看一下

import socket
import threading

def create_socket():
    # 创建一个可以同时支持 IPv4 和 IPv6 的套接字
    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
    
    # 设置地址重用选项,允许快速重启服务器
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    # 设置 IPv6 only 选项为 False,允许 IPv4 客户端连接
    if hasattr(socket, 'IPV6_V6ONLY'):
        sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
    
    return sock

def start_server():
    addr = ("", 8080)  # 监听所有网络接口的 8080 端口
    
    # 尝试创建支持双栈 IPv6 的套接字
    if socket.has_dualstack_ipv6():
        sock = socket.create_server(addr, family = socket.AF_INET6, dualstack_ipv6 = True)
    else:
        # 如果不支持双栈 IPv6,则创建普通的 IPv6 套接字
        sock = socket.create_server(addr)
    
    sock.listen(5)
    print("Server listening on 0.0.0.0:8080 (IPv4 and IPv6)")
    
    while True:
        conn, addr = sock.accept()
        threading.Thread(target = handle_client, args = (conn, addr)).start()

def handle_client(conn, addr):
    print(f"New connection from {addr[0]}:{addr[1]}")
    
    try:
        while True:
            data = conn.recv(1024)
            if not data:
                break
            print(f"Received: {data.decode()}")
            conn.sendall(data)  # 回显收到的数据
    except Exception as e:
        print(f"Error handling client: {e}")
    finally:
        conn.close()
        print(f"Connection closed with {addr[0]}:{addr[1]}")

if __name__ == "__main__":
    start_server()

我们通过 nc 使用 ipv4 协议链接 python 的服务端,可以发现正常触发了ffff::

Untitled

Untitled

并且这种监听会被内核socket 标记为 tcp 46。当然,这里还有一个重要区别,我们以 linux 为例,AP_ENABLE_V4_MAPPED 。这个参数决定了双栈模式下,收到的 ipv4 地址是否翻译为 ipv6 地址去展示。

但是这种技术不知为何鲜为人知,导致测试的同学和绝大多数研发都不知道,以为是 BUG。那我们怎么解决呢?

  1. 关闭ipv6 双栈

  2. 只监听 ipv6

  3. 在 Linux 中,默认情况下,AP_ENABLE_V4_MAPPED 是 1,那么 httpd 就会直接监听 ipv6, 因为此时 ipv6 的 socket 能够处理 ipv4 的请求;另外,bind() 系统调用会对用户空间的进程透明处理 ipv6 没有开启的情况,此时会监听到 ipv4。

    而如果我们在编译 httpd 的时候使用 --disable-v4-mapped 参数禁止 ipv4 mapped,那么默认情况下, httpd 会分别监听在 ipv4 和 ipv6,而非只监听 ipv6

回到我们的业务代码,我们的业务是 Nodejs 开发。在 Nodejs 的 Issues 中,很多人都提到了 ipv6 dual stack 很容易误导人,强烈要求社区关闭该功能。

Untitled

Nodejs 的 socket 监听再没有指定协议的情况下,会使用 Ipv6 dual stack 监听。并且与操作系统有关,Issues 中有人提到,Mac 会默认监听 Tcp46。也就是 ipv4 的请求和 ipv6 的请求不会互相掺杂,但是 ubuntu 却变成了 tcp6.

Untitled

所以,大约在 21 年左右,Nodejs 终于支持了单独设置 Ipv6Only 选项,如图

Untitled

https://github.com/nodejs/help/issues/4067#:~:text=https://nodejs.org/api/net.html#serverlisten

测试由于年少无知,乱提 BUG

标签:socket,Nodejs,sock,IP地址,ffff,ipv4,ipv6,监听,addr
From: https://www.cnblogs.com/unicodeSec/p/18293546

相关文章

  • UE C++获取本机IP地址
    UEC++获取本机IP地址开发环境UE5.2.1VisualStudio201916.11.19代码部分XXX.Build.cs文件添加以下依赖:PrivateDependencyModuleNames.AddRange(newString[]{"Sockets"}).cpp文件:#include"SockerSubsystem.h"voidGetIp(){ boolbBind=false; TSharedRef......
  • [NodeJS] JavaScript模块化
    JavaScript诞生于1995年,一开始只是用于编写简单的脚本。随着前端开发任务越来越复杂,JavaScript代码也越来越复杂,全局变量冲突、依赖管理混乱等问题变得十分突出,模块化成为一个必不可少的功能。模块化发展史与方案对比YUI与JQuery2006年,雅虎开源了组件库YUILibrary,使用类似......
  • NodeJS蔬菜自产零售混合销售平台-计算机毕业设计源码10149
    摘 要随着移动互联网的快速发展,购物方式也发生了巨大的变化。蔬菜作为消费者生活中必不可少的商品之一,在移动互联网时代也迎来了新的购物方式——购物小程序。购物小程序是一种基于手机应用平台的轻量级应用程序,用户可以通过它方便地浏览、选择和购买蔬菜。本文介绍了一个......
  • 如何安全隐藏IP地址,防止网络攻击?
    当您想在互联网上保持隐私或匿名时,您应该做的第一件事就是隐藏您的IP地址。您的IP地址很容易被追踪到您,并被用来了解您的位置。下面的文章将教您如何隐藏自己,不让任何试图跟踪您的活动的人发现。什么是IP地址?首先,让我们稍微讨论一下什么是IP地址。您需要知道的是,每......
  • 如何安全隐藏IP地址,防止网络攻击?
    当您想在互联网上保持隐私或匿名时,您应该做的第一件事就是隐藏您的IP地址。您的IP地址很容易被追踪到您,并被用来了解您的位置。下面的文章将教您如何隐藏自己,不让任何试图跟踪您的活动的人发现。什么是IP地址?首先,让我们稍微讨论一下什么是IP地址。您需要知道的是,每......
  • [NodeJS] Streams流式数据处理
    在现代应用开发中,数据处理的效率和资源管理尤为重要。NodeJS作为一种高效的JavaScript运行时环境,通过其强大的流(Stream)功能,提供了处理大规模数据的便捷方式。流式数据处理不仅能够优化内存使用,还可以提高数据处理的实时性和效率。下文将介绍NodeJS中的流概念、流的类型以及如何利......
  • nodejs编写退出登录的接口逻辑
    目录1.安装必要的依赖2.登录成功生成和返回JWT3.在服务器端维护一个黑名单列表,记录已失效的JWT4.在验证JWT时检查黑名单5.退出登录时将JWT添加到黑名单中完整代码nodejs实现退出登录接口的逻辑,通常包括以下步骤:安装必要的依赖登录成功生成和返回JWT。在服务器......
  • nodejs登录成功生成token并验证
    目录1.安装必要的依赖包2.创建Express应用3.生成token4.使用`express-jwt`验证Token5.错误处理在Node.js中,nodejs登录成功生成token并验证通常涉及以下几个步骤:安装必要的依赖包:常用的库包括 `express`用于创建服务器,`jsonwebtoken`用于处理JWT(JSONWebToken),`expr......
  • [NodeJS] NodeJS运行原理简记
    NodeJS的基本组成NodeJS是JavaScript运行时,主要由V8引擎和libuv组成,其中V8使用javascript和c++编写,而libuv是纯c++编写的,二者都是开源的。V8引擎用于将javascript代码转换为计算机可以执行的机器码;而libuv则负责完成异步IO、与操作系统交互(文件系统和网络模块)、事件循......
  • nodejs和npm安装与配置
    nodejs官网:http://nodejs.cn/百度网盘下载链接:https://pan.baidu.com/s/1RfjeN1bt-I-tf351xi8cgw提取码:sybk下载官网的稳定版msi安装包nodejs默认安装配置了npm进入cmd命令行(以管理员身份打开)node-v npm-v        查看版本,检查安装设置npm淘宝镜像......