Skip to content

Instantly share code, notes, and snippets.

@geberl
Created October 15, 2022 09:27
Show Gist options
  • Save geberl/74ffaaa70be0f31135fa9dc7d30d52b0 to your computer and use it in GitHub Desktop.
Save geberl/74ffaaa70be0f31135fa9dc7d30d52b0 to your computer and use it in GitHub Desktop.
Traceroute a Hetzner Cloud Load Balancer before and after deletion in Go
package main
import (
"fmt"
"net"
"os"
"sync/atomic"
"github.com/aeden/traceroute"
)
// Does not work on macOS (not even with sudo and deactivated firewall), but works nicely from a Hetzner Cloud VM
//
// apt update
// apt upgrade
// apt install golang
// /usr/bin/time -p go run ./traceroute.go
//
// Output if the LB is functional (exits with exit code 0, takes below 2.5 seconds):
//
// traceroute to 65.109.42.205 (65.109.42.205), 64 hops max, 52 byte packets
// 1 _gateway (172.31.1.1) 1.876604ms
// 2 20077.your-cloud.host. (162.55.114.212) 93.587µs
// 3 *
// 4 static.213-239-235-57.clients.your-server.de. (213.239.235.57) 1.152051ms
// 5 core23.fsn1.hetzner.com. (213.239.239.137) 528.986µs
// 6 core5.fra.hetzner.com. (213.239.224.250) 4.963949ms
// 7 core9.fra.hetzner.com. (213.239.252.18) 5.142787ms
// 8 core32.hel1.hetzner.com. (213.239.224.169) 25.059611ms
// 9 spine2.cloud1.hel1.hetzner.com. (88.198.242.250) 25.653479ms
// 10 *
// 11 static.2.131.216.95.clients.your-server.de. (95.216.131.2) 25.191341ms
// 12 static.205.42.109.65.clients.your-server.de. (65.109.42.205) 25.152796ms
//
// Output if the LB was deleted (exits with exit code 1, takes 10 seconds):
//
// traceroute to 65.109.42.205 (65.109.42.205), 16 hops max, 52 byte packets
// 1 _gateway (172.31.1.1) 1.991867ms
// 2 20077.your-cloud.host. (162.55.114.212) 170.878µs
// 3 *
// 4 static.213-239-235-57.clients.your-server.de. (213.239.235.57) 1.095632ms
// 5 core23.fsn1.hetzner.com. (213.239.239.137) 3.375453ms
// 6 core0.fra.hetzner.com. (213.239.252.37) 5.059326ms
// 7 core8.fra.hetzner.com. (213.239.252.9) 5.277316ms
// 8 core31.hel1.hetzner.com. (213.239.224.165) 25.447771ms
// 9 *
// 10 *
// 11 *
// 12 *
// 13 *
// 14 *
// 15 *
// 16 *
func main() {
options := traceroute.TracerouteOptions{}
options.SetRetries(1) // number of probes per time-to-live
options.SetMaxHops(16) // reduced from traceroute.DEFAULT_MAX_HOPS (64) to exit faster; = max time-to-live, for outgoing probe packets
options.SetFirstHop(traceroute.DEFAULT_FIRST_HOP) // 1, first used time-to-live
host := "65.109.42.205"
ipAddr, err := net.ResolveIPAddr("ip", host)
if err != nil {
return
}
fmt.Printf("traceroute to %v (%v), %v hops max, %v byte packets\n", host, ipAddr, options.MaxHops(), options.PacketSize())
var counter uint64
c := make(chan traceroute.TracerouteHop, 0)
go func() {
for {
hop, ok := <-c
if !ok {
fmt.Println()
return
}
atomic.AddUint64(&counter, 1)
printHop(hop)
}
}()
result, err := traceroute.Traceroute(host, &options, c)
if err != nil {
fmt.Printf("Error: %v", err)
}
// In result.Hops only the successful hops (the ones not being *) are counted, use the manual counter instead
// eg for the example above len(result.Hops) would be just 7
fmt.Println(len(result.Hops))
fmt.Println(counter)
if counter > 15 {
os.Exit(1)
}
}
func printHop(hop traceroute.TracerouteHop) {
addr := fmt.Sprintf("%v.%v.%v.%v", hop.Address[0], hop.Address[1], hop.Address[2], hop.Address[3])
hostOrAddr := addr
if hop.Host != "" {
hostOrAddr = hop.Host
}
if hop.Success {
fmt.Printf("%-3d %v (%v) %v\n", hop.TTL, hostOrAddr, addr, hop.ElapsedTime)
} else {
fmt.Printf("%-3d *\n", hop.TTL)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment