发UDP包查询时间服务器NTP

CMakeLists.txt

bash 复制代码
cmake_minimum_required(VERSION 3.13)
project(UDPDateTime C)

set(CMAKE_C_STANDARD 90)

add_executable(UDPDateTime main.c)

* main.c

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <netdb.h>
#include <netinet/in.h>

#define NTP_TIMESTAMP_DELTA 2208988800ull

/* NTP Packet structure */
typedef struct {
    uint8_t li_vn_mode;      /* Eight bits. li, vn, and mode.
                             li.   Two bits.   Leap indicator.
                             vn.   Three bits. Version number of the protocol.
                             mode. Three bits. Client will pick mode 3 for client. */

    uint8_t stratum;         /* Eight bits. Stratum level of the local clock. */
    uint8_t poll;            /* Eight bits. Maximum interval between successive messages. */
    int8_t precision;        /* Eight bits. Precision of the local clock. */

    uint32_t rootDelay;      /* 32 bits. Total round trip delay time. */
    uint32_t rootDispersion; /* 32 bits. Max error aloud from primary clock source. */
    uint32_t refId;          /* 32 bits. Reference clock identifier. */

    uint32_t refTm_s;        /* 32 bits. Reference time-stamp seconds. */
    uint32_t refTm_f;        /* 32 bits. Reference time-stamp fraction of a second. */

    uint32_t origTm_s;       /* 32 bits. Originate time-stamp seconds. */
    uint32_t origTm_f;       /* 32 bits. Originate time-stamp fraction of a second. */

    uint32_t rxTm_s;         /* 32 bits. Received time-stamp seconds. */
    uint32_t rxTm_f;         /* 32 bits. Received time-stamp fraction of a second. */

    uint32_t txTm_s;         /* 32 bits. Transmit time-stamp seconds. */
    uint32_t txTm_f;         /* 32 bits. Transmit time-stamp fraction of a second. */

} ntp_packet;                /* Total: 384 bits or 48 bytes. */

void error(const char *msg) {
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[]) {
    int sockfd, n;
    struct addrinfo hints, *res, *p;
    ntp_packet packet;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s hostname\n", argv[0]);
        exit(0);
    }

    /* Configure the hints for getaddrinfo */
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET6; /* Use IPv6 */
    hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
    hints.ai_protocol = IPPROTO_UDP; /* UDP protocol */

    /* Resolve the hostname to an address */
    if (getaddrinfo(argv[1], "123", &hints, &res) != 0) {
        error("ERROR resolving hostname");
    }

    /* Create a socket */
    sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }

    /* Zero out the packet buffer */
    memset(&packet, 0, sizeof(ntp_packet));

    /* Initialize values needed for NTP request */
    packet.li_vn_mode = 0x1b; /* LI = 0, VN = 3, Mode = 3 (client) */

    /* Iterate through the results from getaddrinfo and send the packet */
    for (p = res; p != NULL; p = p->ai_next) {
        /* Send the packet to the server */
        n = sendto(sockfd, (char *)&packet, sizeof(ntp_packet), 0, p->ai_addr, p->ai_addrlen);
        if (n < 0) {
            error("ERROR sending to socket");
        }

        /* Receive the packet from the server */
        n = recv(sockfd, (char *)&packet, sizeof(ntp_packet), 0);
        if (n < 0) {
            error("ERROR receiving from socket");
        }

        break; /* Exit after successfully sending and receiving a packet */
    }

    /* Free the address info linked list */
    freeaddrinfo(res);

    /* Close the socket */
    close(sockfd);

    /* Interpret the NTP server's response */
    packet.txTm_s = ntohl(packet.txTm_s); /* Time-stamp seconds. */
    packet.txTm_f = ntohl(packet.txTm_f); /* Time-stamp fraction of a second. */

    /* Convert NTP time to UNIX time */
    time_t txTm = (time_t)(packet.txTm_s - NTP_TIMESTAMP_DELTA);

    /* Print the time */
    printf("Time: %s", ctime(&txTm));

    return 0;
}

查询 2.pool.ntp.org

nslookup 2.pool.ntp.org

bash 复制代码
Server:        108.61.10.10
Address:    108.61.10.10#53

Non-authoritative answer:
Name:    2.pool.ntp.org
Address: 162.159.200.1
Name:    2.pool.ntp.org
Address: 162.159.200.123
Name:    2.pool.ntp.org
Address: 133.243.238.243
Name:    2.pool.ntp.org
Address: 45.77.20.103
Name:    2.pool.ntp.org
Address: 2603:1040:404:3::188
Name:    2.pool.ntp.org
Address: 2606:4700:f1::1
Name:    2.pool.ntp.org
Address: 2606:4700:f1::123
Name:    2.pool.ntp.org
Address: 2406:da14:10c4:9aa0:123::

得到UTC时间 2024-06-28 02:44:46 Asia/Shanghai 时区 +8h 10点44

sudo tcpdump -i eth0 host 2.pool.ntp.org -XX

#define NTP_TIMESTAMP_DELTA 2208988800ull /* 这个数字代表1900年到1970年多少秒 */

javascript 复制代码
var lp = 0;
for (var y = 1900; y < 1970; y++) {
    if ((y%400==0) || (y%4==0 && y%100!=0)) {
        lp++;
    }
}
console.log(lp);  /* 17 */
console.log(((1970-1900)*365 + 17)*86400);  /* 2208988800 */

Here's a breakdown of the relevant portions of the tcpdump output:

Packet 1: Sent from telaviv172.xyz to the NTP server (2.pool.ntp.org)

  • Timestamp: 02:44:46.233051
  • Source: telaviv172.xyz (IPv6 address 2a05:f480:2c00:17ff:5400:4ff:fee9:7f7f) on port 58492
  • Destination: any.time.nl.ntp on the NTP port (default 123)
Packet Breakdown:
  • Ethernet Frame:
    • 0x0000: fe00 04e9 7f7f 5600 04e9 7f7f 86dd
  • IPv6 Header:
    • 0x0010: 6000 0000 0038 1140 2a05 f480 2c00 17ff 5400 04ff fee9 7f7f
      • This part includes the source IPv6 address: 2a05:f480:2c00:17ff:5400:4ff:fee9:7f7f
    • 0x0020: 2001 0678 0008 0000 0000 0000 0000 0000 0123 e47c 007b 0038 61db 1b00
      • This part includes the destination IPv6 address and the payload (NTP data).
  • NTP Payload:
    • 0x0030: 0123 e47c 007b 0038 61db 1b00
    • The payload includes NTP data specific to the request.

Packet 2: Response from the NTP server to telaviv172.xyz

  • Timestamp: 02:44:46.233263
  • Source: any.time.nl.ntp on port 123
  • Destination: telaviv172.xyz (IPv6 address 2a05:f480:2c00:17ff:5400:4ff:fee9:7f7f) on port 58492
Packet Breakdown:
  • Ethernet Frame:
    • 0x0000: 5600 04e9 7f7f fe00 04e9 7f7f 86dd
  • IPv6 Header:
    • 0x0010: 6001 4c84 0038 113b 2001 0678 0008 0000 0000 0000 0000 0000 0123
      • This part includes the destination IPv6 address.
    • 0x0020: 2a05 f480 2c00 17ff 5400 04ff fee9 7f7f
      • This part includes the source IPv6 address.
  • NTP Payload:
    • 0x0030: 007b e47c 0038 e542 1c02 00e7 0000 0f8e 0000 0074 1e14 233d ea28
    • The payload includes NTP data specific to the response.

Relevant IPv6 Address Information:

In the first packet, from 0x0016 to 0x0026 byte positions, the IPv6 address 2a05:f480:2c00:17ff:5400:4ff:fee9:7f7f is located as follows:

  • 0x0016: 2a05 f480 2c00 17ff 5400 04ff fee9 7f7f

This matches the IPv6 address of telaviv172.xyz. This part of the packet shows the address in its full form, confirming it as the source address for this packet.

In summary, the tcpdump output confirms a successful NTP query and response transaction between telaviv172.xyz and the NTP server, with the correct IPv6 addresses included in the packets.

Let's break down the Ethernet frame information in more detail:

Ethernet Frame Breakdown:

The Ethernet frame starts from 0x0000 and includes the following information:

  • Destination MAC Address: The first 6 bytes
  • Source MAC Address: The next 6 bytes
  • Type/Length: The following 2 bytes
Ethernet Frame:
  • 0x0000: fe00 04e9 7f7f 5600 04e9 7f7f 86dd
  1. Destination MAC Address:
    • fe:00:04:e9:7f:7f
  2. Source MAC Address:
    • 56:00:04:e9:7f:7f
  3. Type/Length:
    • 0x86dd

Analysis of 0x86dd

  • 0x86dd is the EtherType field in the Ethernet frame.
  • The value 0x86dd indicates that the payload of the Ethernet frame is an IPv6 packet. This is specified by the EtherType for IPv6, which is 0x86dd.

So, the correct interpretation of the Ethernet frame details is:

  • Destination MAC Address: fe:00:04:e9:7f:7f
  • Source MAC Address: 56:00:04:e9:7f:7f
  • Type: 0x86dd (indicating an IPv6 packet)

This means your original interpretation of the MAC addresses and the following two bytes being the EtherType field for IPv6 is correct.

相关推荐
深圳恒讯4 小时前
菲律宾云服务器与传统VPS的架构差异
运维·服务器·架构
蓝天下的守望者4 小时前
svt_apb_if里的宏定义问题
运维·服务器·数据库
小林ixn4 小时前
从“玩具工具”到“跨语言利器”:MCP 协议实战解析
运维·服务器·网络
2603_954708315 小时前
全维度容错设计,打造微电网安全运行屏障
服务器·网络·数据库·人工智能·分布式·安全
其实防守也摸鱼6 小时前
蓝队相关知识学习(1)---常用堡垒机和服务器
服务器·功能测试·学习·网络安全·网络攻击模型·攻防对抗·蓝队
卖萌的斜阳7 小时前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
单片机·网络协议·tcp/ip
用户8334423966147 小时前
Qt6 实现 TCP/UDP/组播 透明中继抓包工具 | 流量录制回放 | 工业设备调试
网络协议
云飞云共享云桌面8 小时前
单机建模卡顿运维繁琐!中小型机械制造厂云飞云 3D 云桌面落地
运维·服务器·网络·3d·自动化·电脑·负载均衡
CryptoPP9 小时前
BSE股票K线数据接入实战:从接口调用到前端图表展示
大数据·前端·网络·人工智能·websocket·网络协议
ITxiaobing20239 小时前
程序化广告RTB场景下IP地理定位服务的精度与工程架构选型
网络协议·tcp/ip·架构