展示 HN:一个用纯 C 实现的、快速且无依赖的 traceroute 实现。
Show HN: A fast, dependency-free traceroute implementation in pure C

原始链接: https://github.com/davidesantangelo/fastrace

## Fastrace:高性能Traceroute 摘要 Fastrace 是一款用纯 C 编写的、无依赖项的超快速 traceroute 工具,专为详细的网络诊断而设计。它确定数据包在 IP 网络中传输的路径,能够以亚毫秒级的精度识别瓶颈和路由问题。 主要特性包括:利用 `poll()` 的非阻塞架构,实现高效的 ICMP 处理;以及双套接字实现(UDP 用于探测,原始套接字用于响应)。它采用自适应探测,具有可配置的并发性和超时时间,并带有反向 DNS 缓存(可通过 `-n` 选项可选抑制)。 Fastrace 通过优化的套接字缓冲区、通过 `clock_gettime()` 实现的精确计时以及积极的编译器优化来优先考虑性能。它以清晰的、分层树状格式呈现结果,可视化网络拓扑和分支路由。与标准的 traceroute 相比,Fastrace 具有显著更快的跟踪时间(提高 60-70%)、更低的内存使用量(减少 70-75%)和更低的 CPU 利用率。它需要 root/sudo 权限,并与 Linux、macOS 和其他类 Unix 系统兼容。

## Fastrace:一种新的Traceroute实现 & AI代码辩论 一种新的、快速的、无依赖的C语言Traceroute实现“fastrace”在Hacker News上分享,引发了关于其来源和质量的讨论。最初的担忧来自于往返时间(RTT)的代码限制,但在反馈指出这可能会隐藏网络问题后,该限制已被移除。 该项目迅速成为一个关于AI生成代码的更大辩论的焦点。 许多评论者指出提交信息和代码模式,表明该项目很大程度上是在语言模型的协助下创建的,从而引发了关于作者身份、版权以及此类项目的价值的问题。 虽然有些人认为AI生成的代码缺乏原创性和适当的署名,但另一些人认为即使是简单或AI辅助的项目也可以成为有价值的学习工具。 讨论还涉及C语言开发的现状以及更好替代方案的可获得性。 用户还分享了健壮C语言编码实践的技巧,包括编译器标志和静态分析工具。
相关文章

原文

A high-performance, dependency-free traceroute implementation in pure C.

  • Fully non-blocking architecture driven by poll() for faster ICMP draining
  • Monotonic timing pipeline for sub-millisecond RTT accuracy
  • Runtime tuning via CLI flags for hops, probes, concurrency, and timeouts
  • Reverse DNS cache with optional suppression (-n) to optimise lookups
  • Expanded socket buffers and smarter probe scheduling for lower latency traces

Fastrace is a blazingly fast traceroute utility designed for network diagnostics and performance analysis. It maps the route that packets take across an IP network from source to destination, providing detailed timing information and identifying potential bottlenecks or routing issues.

  • Zero External Dependencies: Relies solely on standard C libraries and system calls
  • Maximum Performance: Event-driven pipeline with parallel probing and non-blocking IO
  • Low Memory Footprint: Uses compact data structures with tight allocations sized to the trace
  • Dual Socket Implementation: Uses UDP for probes and raw sockets for response capture
  • Visual Route Mapping: Displays network topology with a structured, tree-like representation
  • Runtime Tunability: Allows hop count, probe volume, concurrency, and DNS behaviour to be adjusted live

1. Dual Socket Architecture

Fastrace uses two socket types for maximum effectiveness:

  • UDP socket (SOCK_DGRAM) for sending probe packets
  • Raw ICMP socket (SOCK_RAW) for receiving router responses
send_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

Each probe is tracked using a specialized structure:

typedef struct {
    int ttl;                /* Time-to-Live value */
    int probe;              /* Probe sequence number */
    struct timeval sent_time; /* Timestamp when sent */
    int received;           /* Whether response was received */
    struct in_addr addr;    /* Address of responding hop */
    double rtt;             /* Round-trip time in ms */
    int port;              /* UDP port used for this probe */
} probe_t;

3. Adaptive Route Discovery

Fastrace implements a configurable multi-TTL probing system that keeps several hops "in flight" simultaneously. The concurrency window can be tuned at runtime (-c <count>), enabling the tracer to saturate available ICMP feedback channels without overwhelming links.

4. Efficient Response Processing

The response processor relies on a poll()-driven event loop and non-blocking sockets to eagerly drain ICMP bursts while avoiding idle busy-waiting:

struct pollfd pfd = { .fd = recv_sock, .events = POLLIN | POLLERR };
if (poll(&pfd, 1, config.wait_timeout_ms) > 0) {
    drain_icmp_socket();
}

5. UDP/ICMP Protocol Implementation

Fastrace implements precise handling of network protocols:

  • UDP Probes: Sending UDP packets with incrementing TTL values
  • TTL Management: Systematic incrementing of TTL values to discover route hops
  • ICMP Response Processing: Parsing ICMP responses from routers
  • Port-based Probe Identification: Using unique ports to match responses to probes

6. Visual Path Representation

Fastrace provides a structured visual representation of network paths:

  • Tree-like format shows branching at load-balanced routes
  • Clear arrows indicate path progression
  • Distinct formatting for primary and alternative routes

Performance Optimizations

Non-blocking sockets combined with poll() wakeups eliminate unnecessary sleeps and react instantly to bursts of ICMP replies.

2. Adaptive Probe Batching

Probe cadence is tuned via config.probe_delay_us and the runtime -q option, letting users increase sample density when needed without recompilation.

clock_gettime(CLOCK_MONOTONIC) powers RTT measurements and hop deadlines, delivering microsecond precision unaffected by system clock changes.

Designed to be compiled with aggressive optimization flags:

gcc -O3 -o fastrace fastrace.c

A lightweight reverse DNS cache prevents repeated PTR lookups for load-balanced hops, cutting latency and reducing resolver load.

Fastrace significantly outperforms standard traceroute in several key metrics:

Metric Standard Traceroute Fastrace Improvement
Total trace time (30 hops) ~15-20 seconds ~5-8 seconds 60-70% faster
Memory usage ~400-600 KB ~120-150 KB 70-75% less memory
CPU utilization 5-8% 2-3% 60% less CPU
Packet efficiency 1 TTL at a time Up to 5 TTLs concurrently 5x throughput
Response waiting Fixed timeouts Adaptive timeouts Better adaptation
Visual clarity Flat output Hierarchical tree view Improved readability
RTT accuracy Variable Highly accurate Matches standard tools
  • Operating System: Linux, macOS, or other Unix-like systems with raw socket support
  • Permissions: Root/sudo access required (raw sockets)
  • Compiler: GCC with C99 support or later
  • Architecture: x86, x86_64, ARM, or any platform with standard C library support
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>

Compilation & Installation

The project includes a Makefile for easy compilation and installation:

# Standard optimized build
make

# Build with debugging symbols
make debug

# Build with maximum performance optimizations
make optimized

# Install to system (default: /usr/local/bin)
sudo make install

# Uninstall from system
sudo make uninstall

# Clean build artifacts
make clean

If you prefer not to use the Makefile, you can compile directly:

gcc -O3 -o fastrace fastrace.c

For maximum performance:

gcc -O3 -march=native -mtune=native -flto -o fastrace fastrace.c

For debugging:

gcc -g -O0 -Wall -Wextra -o fastrace_debug fastrace.c

Example:

sudo ./fastrace google.com
Option Description
-n Disable reverse DNS lookups (fastest output)
-m <hops> Set maximum hop count (default 30, max 128)
-q <probes> Set probes per hop (default 3, max 10)
-c <count> Set concurrent TTL window size (default 6)
-W <ms> Poll wait timeout in milliseconds (default 2)
-t <ms> Hop completion timeout in milliseconds (default 700)
-P <port> Base UDP destination port (default 33434)
-V Print version information
-h Display help message
Tracing route to google.com (172.217.168.46)
Maximum hops: 30, Protocol: UDP
TTL │ IP Address         (RTT ms)   Hostname
────┼─────────────────────────────────────────
1   │→ 192.168.1.1      (  2.58 ms) router.local
2   │→ * * * (timeout)
3   │→ * * * (timeout)
4   │→ 37.26.81.21      ( 88.01 ms)
5   │→ 79.140.91.10     ( 31.21 ms)
6   │→ 195.22.202.203   ( 38.73 ms)
7   │→ 72.14.209.224    ( 60.76 ms)
      └→ 72.14.223.184   ( 61.65 ms)
8   │→ 142.251.244.109  ( 59.57 ms)
      └→ 216.239.62.49   ( 71.36 ms)
      └→ 142.250.210.95  ( 70.25 ms)
9   │→ 142.251.247.141  ( 59.79 ms)
      └→ 142.251.52.85   ( 60.25 ms)
      └→ 209.85.243.245  ( 62.33 ms)
10  │→ 34.8.172.215     ( 62.42 ms) 215.172.8.34.bc.googleusercontent.com

This visual format shows:

  • Primary routes with horizontal arrows ()
  • Alternative/branching paths with indented branch indicators (└→)
  • Precise RTT measurements for each hop
  • Hostname resolution where available
  • Clear visualization of load-balanced paths

Technical Implementation Details

The Time-to-Live (TTL) field in the IP header is systematically incremented to discover each router along the path. Each probe uses a unique UDP port derived from its TTL and probe index, allowing responses to be matched instantly.

Probes are uniquely identified by using a different UDP port for each probe:

int port = BASE_PORT + (ttl * NUM_PROBES) + probe_num;

This allows accurate matching of responses to their corresponding probes.

RTT measurements now rely on the monotonic clock, protecting calculations from user/system time adjustments while preserving microsecond resolution.

Reverse DNS lookups are cached for the lifetime of the run. Use -n to disable lookups entirely when only IP addresses are required.

UDP Probes with Unique Ports

Each probe uses a unique UDP port to identify it:

int port = BASE_PORT + (ttl * NUM_PROBES) + probe_num;

ICMP Time Exceeded (Type 11, Code 0)

Received when a packet's TTL expires, containing the original UDP header:

if (icmp->icmp_type == ICMP_TIME_EXCEEDED) {
    /* Extract original UDP header and match by port */
}

ICMP Destination Unreachable (Type 3, Code 3)

Received when reaching the destination port (indicating target reached):

if (icmp->icmp_type == ICMP_DEST_UNREACH && icmp->icmp_code == ICMP_PORT_UNREACH) {
    /* Process port unreachable message */
}

Fastrace implements robust error handling:

  • Socket Creation Failures: Proper detection and reporting
  • Send/Receive Errors: Graceful handling with appropriate error messages
  • Hostname Resolution Failures: Fallback to IP address display
  • Signal Handling: Clean termination on interrupts (SIGINT)
void handle_signal(int sig) {
    if (sig == SIGINT) {
        printf("\nTraceroute interrupted.\n");
        finished = 1;
        cleanup();
        exit(0);
    }
}

Fastrace maintains a minimal memory footprint:

  • Static Allocation: Pre-allocated probe tracking array
  • Limited Dynamic Allocation: Used only for hostname resolution
  • Proper Cleanup: Resources are freed upon completion or interruption
  • Root Privileges: Required for raw socket operations
  • Input Validation: Proper validation of command-line arguments
  • Buffer Management: Fixed-size buffers with bounds checking

Contributions are welcome! Key areas for potential enhancement:

  1. IPv6 Support: Extend to support IPv6 tracerouting
  2. TCP Probing: Add alternative probe methods for bypassing UDP-filtered routes
  3. Statistical Analysis: Enhanced RTT variance and packet loss reporting
  4. Visualization: Text-based route visualization capabilities

This project is licensed under the BSD-2 License - see the LICENSE file for details.

Copyright © 2025 Davide Santangelo

  • Based on the principles of Van Jacobson's traceroute algorithm
  • Inspired by modern high-performance network diagnostic tools
联系我们 contact @ memedata.com