Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trippy 0.11.0 #180845

Merged
merged 2 commits into from
Aug 11, 2024
Merged

trippy 0.11.0 #180845

merged 2 commits into from
Aug 11, 2024

Conversation

BrewTestBot
Copy link
Member

Created by brew bump


Created with brew bump-formula-pr.

release notes
## Highlights

This release of Trippy adds NAT detection for IPv4/UDP/Dublin tracing, a new public API, reverse DNS lookup cache
time-to-live, transient error handling for IPv4, a new ROFF manual page generator, several new columns, improved error
messages and a revamped help dialog with settings tab hotkeys.

There are two breaking changes, a new initial sequence number is used which impacts the default behaviour of UDP tracing
and two configuration fields have been renamed and moved.

Finally, there are a handful of bug fixes and two new distribution packages, Chocolatey and an official PPA for Ubuntu
and Debian based distributions.

NAT Detection for IPv4/UDP/Dublin

When tracing with the Dublin tracing strategy for IPv4/UDP, Trippy can now detect the presence of NAT (Network Address
Translation) devices on the path.

NAT devices are detected by observing a difference in the expected and actual checksum of the UDP packet header that
is returned as the part of the Original Datagram in the ICMP Time Exceeded message. Any difference is indicative of a
NAT device that has modified the packet in flight. This happens because the NAT device must recalculate the UDP checksum
after modifying the packet and so the checksum in the ICMP error will not match the original checksum.

To help illustrate the technique, when sending the following IPv4/UDP packet (note the IPv4 Checksum A and
UDP Checksum B):

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|Version|  IHL  |Type of Service|          Total Length         | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|         Identification        |Flags|     Fragment Offset     | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|  Time to Live |    Protocol   |            Checksum A         | │ IPv4 Header 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|                         Source Address                        | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|                      Destination Address                      | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
                                                                                
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │             
|          Source Port          |        Destination Port       | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ UDP Header  
|             Length            |            Checksum B         | │             
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                                                                             

Trippy expect to receive an ICMP TimeExceeded error which contains the Original Datagram (OD) IPv4/UDP packet that was
sent above with Checksum A' and Checksum B' in the Original Datagram (OD) IPv4/UDP packet:

 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |Version|  IHL  |Type of Service|          Total Length         | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |         Identification        |Flags|     Fragment Offset     | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |  Time to Live |    Protocol   |            Checksum C         | │ IPv4 Header                        
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |                         Source Address                        | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |                      Destination Address                      | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
                                                                                                        
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
 |      Type     |      Code     |            Checksum D         | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ IPv4 Payload (ICMP TE Header)      
 |                             Unused                            | │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │                                    
                                                                   │                                    
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
 |Version|  IHL  |Type of Service|          Total Length         | │ │                                  
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
 |         Identification        |Flags|     Fragment Offset     | │ │                                  
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
 |  Time to Live |    Protocol   |            Checksum A'        | │ │ ICMP TE Payload (OD IPv4 Header) 
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
 |                         Source Address                        | │ │                                  
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
 |                      Destination Address                      | │ │                                  
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │                                  
                                                                   │ │                                  
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │ │                                
 |          Source Port          |        Destination Port       | │ │ │                                
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │ │ OD IPv4 Payload (UDP header)   
 |             Length            |            Checksum B'        | │ │ │                                
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ │ │ │                                

If Checksum B' in the ICMP error does not match the Checksum B in the UDP packet that was sent then Trippy can infer
that a NAT device has modified the packet.

This functionally is only possible when the Dublin tracing strategy is used at it does not modify the UDP header per
probe and as such the checksums are expected to be constant for all hops. This allows detection multiple NAT devices on
the path as changes to the checksum between consecutive hops indicates the presence of a NAT device.

Note that this method cannot detect all types of NAT devices and so should be used in conjunction with other methods
where possible.

See the issue for more details.

Public API

Trippy has been designed primarily a standalone tool, however it is built on top of a number of useful libraries,
such as the core tracer, DNS resolver and more. These libraries have always existed but were tightly integrated into
the tool and not designed to be used by third party crates.

This release introduces the Trippy public API which can be used to build custom tools on top of the Trippy libraries.

The full set of libraries exposed is:

Crate Description
trippy Common entrypoint crate
trippy-core The core Trippy tracing functionality
trippy-packet Packet wire formats and packet parsing functionality
trippy-dns Perform forward and reverse lazy DNS resolution
trippy-privilege Discover platform privileges
trippy-tui The Trippy terminal user interface

To use the Trippy public API you should add the common entrypoint trippy crate to your Cargo.toml file and then
enable the desired features. Note that the trippy crate includes tui as a default feature and so you should disable
default features when using it as a library. Alternatively, it is also possible to add the crates individually.

For example, to use the core Trippy tracing functionality you would add the trippy crate, disable default features and
enable the core feature:

[dependencies]
trippy = { version = "0.11.0", default-features = false, features = ["core"] }

The hello-world example below demonstrates how to use the Trippy public API to perform a simple trace and print the
results of each round:

use std::str::FromStr;
use trippy::core::Builder;

fn main() -> anyhow::Result<()> {
    let addr = std::net::IpAddr::from_str("1.1.1.1")?;
    Builder::new(addr)
        .build()?
        .run_with(|round| println!("{:?}", round))?;
    Ok(())
}

Whilst Trippy adheres to Semantic Versioning, the public API is not yet considered stable and
may change in future releases.

See crates and the usage examples for more information.

New Initial Sequence

For UDP tracing, by default Trippy uses a fixed src port and a variable destination port which is set from the sequence
number, starting from an initial sequence of 33000 and incremented for each probe, eventually wrapping around.

By convention, many devices on the internet allow UDP
probes to ports in the range 33434..=33534 and will return a DestinationUnreachable ICMP error which can be used to
confirm that the target has been reached. As Trippy does not, by default, use destination ports in this range for UDP
probes, the target host does not respond with an ICMP error and so Trippy cannot know that the target was reached and
must therefore show the hop as unknown.

After running for several rounds, the sequence number will enter into the range 33434..=33534 and the target will begin
to respond with the DestinationUnreachable ICMP error, however there is no guarantee that the probe sent for sequence
33434 corresponds to the smallest time-to-live (ttl) value sent and so the target which responds may have a larger ttl
than expected. This leads to very confusing output which is very hard for users to interpret.
See issue for more details.

This problem can be overcome today either by changing the initial sequence number to be in the range 33434..=33534 by
setting the --initial-sequence flag or by using a fixed destination port (and therefore a variable source port) in the
same range by setting the --target-port flag.

In the following example, the initial sequence number is set to 33434:

trip example.com --udp --initial-sequence 33434

This can be made permanent by setting the initial-sequence value in the strategy section of the configuration file:

[strategy]
initial-sequence = 33434

In the following example, the destination port is set to 33434:

trip example.com --udp --target-port 33434

This can be made permanent by setting the target-port value in the strategy section of the configuration file:

[strategy]
target-port = 33434

Note that for TCP tracing, by default, the destination port is fixed (defaults to 80) and so this issue does not
typically arise.

As the current default behaviour in Trippy is confusing, in this release the default sequence number has been changed
to be 33434. This a breaking change and will impact users who rely on the old default initial sequence number.

This change also introduces a new problem; UDP traces will now begin with a target port of 33434 and
so DestinationUnreachable ICMP errors will typically be returned by the target. However, but after several
rounds of tracing the sequence number will move beyond the range 33434..=33534 and so the target host will stop
responding with DestinationUnreachable ICMP errors. This leads to the appearance that the target has started dropping
packets. Whilst technically correct, this is not desirable behaviour as the target has not changed, only the sequence
number has changed.

It is therefore recommended to always fix the target-port to be in the range 33434..=33534 for UDP tracing and allow
the source port to vary instead. This may become the default behaviour for UDP tracing in a future release. Note that
this would differ from the behaviour of most traditional Unix traceroute tools which vary the destination port by
default.

Reverse DNS Lookup Cache Time-to-live

Trippy performs a reverse DNS lookup for each host encountered during the trace and the resulting hostnames are cached
indefinitely. This can lead to stale hostnames being displayed in the TUI if they change after the trace has begun.

Note that the DNS cache can be flushed manually by pressing ctrl+k (default key binding) in the TUI.

Starting from this release the reverse DNS cache can be configured to expire after a certain time to live. By default
this is set to be 5 minutes (300 seconds) and can be configured using the --dns-ttl flag or the dns-ttl
configuration option.

The following example sets the DNS cache time-to-live to 30 seconds:

trip example.com --dns-ttl 30s

This can be made permanent by setting the dns-ttl value in the dns section of the configuration file:

[dns]
dns-ttl = "30s"

Transient Error Handling for IPv4

Trippy records the number of probes sent and the number of probes received for each hop and uses this information to
calculate packet loss. Any probe that is successfully sent for which no response is received is considered lost.

Currently, if a probe cannot be sent for any reason then Trippy will crash and show a BSOD. This is not typically an
issue, as such failures imply a local issue with the host network configuration rather than an issue with the target or
any intermediate hops.

It is however possible that a probe may fail to send for a transient reason, such as a temporary local host issue, and
so it would be useful to be able to handle such errors gracefully. A common example would be running Trippy on a host
and during the trace disabling the network interface.

Starting from this release, Trippy will continue the trace even if a probe fails to send and will instead show a warning
to the user in the TUI about number of probe failures. A new column (hidden by default), Fail, has also been added to
the TUI to show the number of probes which failed to send for each hop.

This has been implemented for macOS, Linux and Windows for IPv4 only. Support for IPv6 and other platforms will be added
in future releases. See the tracking issue for more details.

Generate ROFF Man Page

Trippy can now generate manual pages in ROFF format. This can be useful for users who wish to install Trippy on systems
which do not have a package manager or for users who wish to install Trippy from source. It can also be used by package
maintainers to generate manual pages for their distribution.

The following command generates a ROFF manual page for Trippy:

trip --generate-man > /path/to/man/pages/trip.1

New Columns

This release introduced several new columns, all of which are hidden by default. These are:

  • ICMP Type: The ICMP packet type for the last probe for the hop
  • ICMP Code: The ICMP packet code for the last probe for the hop
  • NAT detection status: The NAT detection status for the hop
  • Probe failures: The number of probes which failed to send for the hop

The following shows the ICMP type and code columns:

See the Column Reference for a full list of all available
columns.

Settings Dialog Tab Hotkeys

The settings dialog can be accessed by pressing s (default key binding) and users can navigate between the tabs using
the left and right arrow keys (default key bindings). This release introduces hotkeys to allow users to jump directly to
a specific tab by pressing 1-7 (default key bindings).

See the Key Bindings Reference for details.

Help Dialog Revamped

The existing Trippy help dialog shows a hardcoded list of key bindings which may not reflect the actual key bindings the
user has configured. Trippy shows the correct key bindings in the settings dialog which can be accessed by
pressing s (default key binding) and navigating the the Bindings tab. Therefore the key bindings in the help dialog
are both potentially incorrect and redundant.

This release revamps the help dialog and includes instructions on how to access the key bindings from the settings
dialog as well as some other useful information.

Improved Error Messages

Error reporting has been improved for parameters such as --min-round-duration (-i). Previously, if an invalid
duration was provided, the following error would be reported:

$ trip example.com -i 0.05
Error: invalid character at 1

Starting from this release, such error will instead be shown as:

$ trip example.com -i 0.05
error: invalid value '0.05' for '--min-round-duration <MIN_ROUND_DURATION>': expected time unit (i.e. 100ms, 2s, 1000us)

For more information, try '--help'.

This covers all "duration" parameters, namely:

  • min_round_duration
  • max_round_duration
  • grace_duration
  • read_timeout
  • dns_timeout
  • tui_refresh_rate

Renamed Configuration

The following configuration fields have been renamed and moved from the [tui] to the [strategy] section in the
configuration file:

  • tui-max-samples -> max-samples
  • tui-max-flows -> max-flows

This is a breaking change. Attempting to use the legacy field names will result in an error pointing to the new
name.

The following examples shows the error reported if the old names are used from the command line:

error: unexpected argument '--tui-max-samples' found

  tip: a similar argument exists: '--max-samples'

The following examples shows the error reported if the ld names are used from the configuration file:

Error: tui-max-samples in [tui] section is deprecated, use max-samples in [strategy] section instead

Bug Fixes

This release fixes a bug where DestinationUnreachable ICMP errors were assumed to have been sent by the target host,
whereas they may also be sent by an intermediate hop.

Another fix addresses an issue where the TUI would calculate the maximum number of hops to display based on the maximum
observed across all rounds rather than for the latest round.

Finally, a minor bug was fixed where AddressInUse and AddrNotAvailable errors were being conflated.

New Distribution Packages

Trippy has been added to the Chocolatey community repository (with thanks to @Aurocosh!):

Chocolatey package

choco install trippy

Trippy also has an official PPA for Ubuntu and Debian based distributions (with thanks to @zarkdav!):

Ubuntu PPA

sudo add-apt-repository ppa:fujiapple/trippy
sudo apt update && apt install trippy

You can find the full list of distributions in the
documentation.

Thanks

My thanks to all Trippy contributors, package maintainers and community members.

Feel free to drop by the new Trippy Zulip room for a chat:

project chat

Happy Tracing!

Change Log

Added

  • Added NAT detection for IPv4/udp/dublin (#1104)
  • Added public API (#1192)
  • Added support for NAT detection (N) column (#1219)
  • Added support for last icmp packet type (T) column (#1105)
  • Added support for last icmp packet code (C) column (#1109)
  • Added support for the probe failure count (f) column (#1258)
  • Added settings dialog tab hotkeys (#1217)
  • Added --dns-ttl flag to allow refreshing the reverse DNS results (#1233)
  • Added --generate-man flag for generating ROFF man page (#85)
  • Added Ubuntu PPA package (#859)
  • Added Chocolatey package (#572)

Changed

  • [BREAKING CHANGE] Changed initial sequence to be 33434 (#1203)
  • [BREAKING CHANGE] Renamed tui-max-[samples|flows] as max-[samples|flows] (#1187)
  • Separated library and binary crates (#1141)
  • Record icmp packet code (#734)
  • Transient error handling for IPv4 on macOS, Linux & Windows (#1255)
  • Improved error messages (#1150)
  • Revamp the help dialog (#1260)

Fixed

  • Fixed DestinationUnreachable incorrectly assumed to come from target host ([#1225 (https://github.com/fujiapple852/trippy/issues/1225))
  • Fixed incorrect target hop calculation (#1226)
  • Do not conflate AddressInUse and AddrNotAvailable errors (#1246)

See CHANGELOG.md for details.

Full Changelog: fujiapple852/trippy@0.10.0...0.11.0

@github-actions github-actions bot added rust Rust use is a significant feature of the PR or issue bump-formula-pr PR was created using `brew bump-formula-pr` labels Aug 11, 2024
trippy: update build

Signed-off-by: Rui Chen <[email protected]>
@chenrui333 chenrui333 added the ready to merge PR can be merged once CI is green label Aug 11, 2024
Copy link
Contributor

@github-actions github-actions bot added the CI-published-bottle-commits The commits for the built bottles have been pushed to the PR branch. label Aug 11, 2024
@BrewTestBot BrewTestBot added this pull request to the merge queue Aug 11, 2024
Merged via the queue into master with commit 146d036 Aug 11, 2024
15 checks passed
@BrewTestBot BrewTestBot deleted the bump-trippy-0.11.0 branch August 11, 2024 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bump-formula-pr PR was created using `brew bump-formula-pr` CI-published-bottle-commits The commits for the built bottles have been pushed to the PR branch. ready to merge PR can be merged once CI is green rust Rust use is a significant feature of the PR or issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants