diff --git a/.gitignore b/.gitignore index 5bd2a8d..dc238eb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ *.dylib build go/dublintraceroute/cmd/dublin-traceroute/dublin-traceroute +go/dublintraceroute/cmd/routest/routest +.travis/trace.json +integ/trace.json diff --git a/include/dublintraceroute/dublin_traceroute.h b/include/dublintraceroute/dublin_traceroute.h index 5c2fa92..7230e44 100644 --- a/include/dublintraceroute/dublin_traceroute.h +++ b/include/dublintraceroute/dublin_traceroute.h @@ -51,6 +51,7 @@ class DublinTraceroute { const bool broken_nat_, use_srcport_for_path_generation_, no_dns_; + std::string interface_; std::mutex mutex_tracerouting, mutex_sniffed_packets; IPv4Address my_address; @@ -67,6 +68,7 @@ class DublinTraceroute { static const bool default_broken_nat = false; static const bool default_use_srcport_for_path_generation = false; static const bool default_no_dns = false; + static const std::string default_interface; DublinTraceroute( const std::string &dst, const uint16_t srcport = default_srcport, @@ -77,7 +79,8 @@ class DublinTraceroute { const uint16_t delay = default_delay, const bool broken_nat = default_broken_nat, const bool use_srcport_for_path_generation = default_use_srcport_for_path_generation, - const bool no_dns = default_no_dns + const bool no_dns = default_no_dns, + const std::string interface = default_interface ): srcport_(srcport), dstport_(dstport), @@ -88,7 +91,8 @@ class DublinTraceroute { delay_(delay), broken_nat_(broken_nat), use_srcport_for_path_generation_(use_srcport_for_path_generation), - no_dns_(no_dns) + no_dns_(no_dns), + interface_(interface) { validate_arguments(); } DublinTraceroute( const char *dst, @@ -100,7 +104,8 @@ class DublinTraceroute { const uint16_t delay = default_delay, const bool broken_nat = default_broken_nat, const bool use_srcport_for_path_generation = default_use_srcport_for_path_generation, - const bool no_dns = default_no_dns + const bool no_dns = default_no_dns, + const std::string interface = default_interface ): srcport_(srcport), dstport_(dstport), @@ -111,7 +116,8 @@ class DublinTraceroute { delay_(delay), broken_nat_(broken_nat), use_srcport_for_path_generation_(use_srcport_for_path_generation), - no_dns_(no_dns) + no_dns_(no_dns), + interface_(interface) { validate_arguments(); } ~DublinTraceroute() { std::lock_guard lock(mutex_tracerouting); }; DublinTraceroute(const DublinTraceroute& source): @@ -124,7 +130,8 @@ class DublinTraceroute { delay_(source.delay_), broken_nat_(source.broken_nat_), use_srcport_for_path_generation_(source.use_srcport_for_path_generation_), - no_dns_(source.no_dns_) + no_dns_(source.no_dns_), + interface_(source.interface_) { validate_arguments(); } inline const uint16_t srcport() const { return srcport_; } @@ -135,6 +142,7 @@ class DublinTraceroute { inline const uint16_t delay() const { return delay_; } inline const bool broken_nat() const { return broken_nat_; } inline const bool no_dns() const { return no_dns_; } + inline const std::string interface() const { return interface_; } inline const bool use_srcport_for_path_generation() const { return use_srcport_for_path_generation_; } inline const std::string &dst() const { return dst_; } inline const IPv4Address &target() const { return target_; } diff --git a/include/dublintraceroute/udpv4probe.h b/include/dublintraceroute/udpv4probe.h index eb43db2..de31b50 100644 --- a/include/dublintraceroute/udpv4probe.h +++ b/include/dublintraceroute/udpv4probe.h @@ -25,6 +25,7 @@ class UDPv4Probe { uint16_t local_port_; uint16_t remote_port_; uint8_t ttl_; + std::string interface_; IP *packet = nullptr; public: @@ -33,17 +34,20 @@ class UDPv4Probe { const uint16_t local_port() const { return local_port_; }; const uint16_t remote_port() const { return remote_port_; }; const uint8_t ttl() const { return ttl_; }; + const std::string interface() const { return interface_; }; UDPv4Probe( IPv4Address remote_addr, uint16_t remote_port, uint16_t local_port, uint8_t ttl, + std::string interface = "", IPv4Address local_addr = 0): remote_addr_(remote_addr), remote_port_(remote_port), local_port_(local_port), ttl_(ttl), + interface_(interface), local_addr_(local_addr) { }; ~UDPv4Probe(); IP* forge(); diff --git a/src/dublin_traceroute.cc b/src/dublin_traceroute.cc index e079852..977764f 100644 --- a/src/dublin_traceroute.cc +++ b/src/dublin_traceroute.cc @@ -41,6 +41,8 @@ extern int errno; #define SNIFFER_TIMEOUT_MS 2000 +// this is not necessary in C++17 and can be assigned in the header file. +const std::string DublinTraceroute::default_interface = ""; Tins::Timestamp extract_timestamp_from_msg(struct msghdr &msg) { int level, type; @@ -218,10 +220,10 @@ std::shared_ptr DublinTraceroute::traceroute() { UDPv4Probe *probe = NULL; if(use_srcport_for_path_generation()){ - probe = new UDPv4Probe(target(), dstport(), iterated_port, ttl); + probe = new UDPv4Probe(target(), dstport(), iterated_port, ttl, interface()); } else{ - probe = new UDPv4Probe(target(), iterated_port, srcport(), ttl); + probe = new UDPv4Probe(target(), iterated_port, srcport(), ttl, interface()); //UDPv4Probe probe(target(), dport, srcport(), ttl); } IP *packet; diff --git a/src/main.cc b/src/main.cc index 5a145f9..c473c25 100644 --- a/src/main.cc +++ b/src/main.cc @@ -32,6 +32,7 @@ const struct option longopts[] = { {"broken-nat", no_argument, NULL, 'b'}, {"use-srcport", no_argument, NULL, 'i'}, {"no-dns", no_argument, NULL, 'N'}, + {"interface", required_argument, NULL, 'I'}, {"output-file", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0}, }; @@ -51,23 +52,25 @@ R"(Written by Andrea Barberio - https://insomniac.slackware.it [--broken-nat] [--use-srcport] [--no-dns] + [--interface=ifname] [--output-file=file_name] [--help] [--version] Options: - -h --help this help - -v --version print the version of Dublin Traceroute - -s SRC_PORT --sport=SRC_PORT the source port to send packets from (default: )" << DublinTraceroute::default_srcport << R"() - -d DST_PORT --dport=DST_PORT the base destination port to send packets to (default: )" << DublinTraceroute::default_dstport << R"() - -n NPATHS --npaths=NPATHS the number of paths to probe (default: )" << static_cast(DublinTraceroute::default_npaths) << R"() - -t MIN_TTL --min-ttl=MIN_TTL the minimum TTL to probe (default: )" << static_cast(DublinTraceroute::default_min_ttl) << R"() - -T MAX_TTL --max-ttl=MAX_TTL the maximum TTL to probe. Must be greater or equal than the minimum TTL (default: )" << static_cast(DublinTraceroute::default_max_ttl) << R"() - -D DELAY --delay=DELAY the inter-packet delay in milliseconds (default: )" << DublinTraceroute::default_delay << R"() - -b --broken-nat the network has a broken NAT configuration (e.g. no payload fixup). Try this if you see fewer hops than expected - -i --use-srcport generate paths using source port instead of destination port - -N --no-dns do not attempt to do reverse DNS lookup of the hops - -o --output-file the output file name (default: )" << DEFAULT_OUTPUT_FILE << R"() + -h, --help this help + -v, --version print the version of Dublin Traceroute + -s, --sport=SRC_PORT the source port to send packets from (default: )" << DublinTraceroute::default_srcport << R"() + -d, --dport=DST_PORT the base destination port to send packets to (default: )" << DublinTraceroute::default_dstport << R"() + -n, --npaths=NPATHS the number of paths to probe (default: )" << static_cast(DublinTraceroute::default_npaths) << R"() + -t, --min-ttl=MIN_TTL the minimum TTL to probe (default: )" << static_cast(DublinTraceroute::default_min_ttl) << R"() + -T, --max-ttl=MAX_TTL the maximum TTL to probe. Must be greater or equal than the minimum TTL (default: )" << static_cast(DublinTraceroute::default_max_ttl) << R"() + -D, --delay=DELAY the inter-packet delay in milliseconds (default: )" << DublinTraceroute::default_delay << R"() + -b, --broken-nat the network has a broken NAT configuration (e.g. no payload fixup). Try this if you see fewer hops than expected + -i, --use-srcport generate paths using source port instead of destination port + -N, --no-dns do not attempt to do reverse DNS lookup of the hops + -I, --interface=INTERFACE force packets through the specified interface. If not specified, the default interface for the target will be used + -o, --output-file=OUTFILE the output file name (default: )" << DEFAULT_OUTPUT_FILE << R"() See documentation at https://dublin-traceroute.net @@ -89,6 +92,7 @@ main(int argc, char **argv) { bool broken_nat = DublinTraceroute::default_broken_nat; bool use_srcport_for_path_generation = DublinTraceroute::default_use_srcport_for_path_generation; bool no_dns = DublinTraceroute::default_no_dns; + std::string interface = DublinTraceroute::default_interface; std::string output_file = DEFAULT_OUTPUT_FILE; if (geteuid() == 0) { @@ -143,6 +147,9 @@ main(int argc, char **argv) { case 'N': no_dns = true; break; + case 'I': + interface = optarg; + break; case 'o': output_file.assign(optarg); break; @@ -215,18 +222,24 @@ main(int argc, char **argv) { delay, broken_nat, use_srcport_for_path_generation, - no_dns + no_dns, + interface ); std::cout << "Traceroute from 0.0.0.0:" << Dublin.srcport(); - if(use_srcport_for_path_generation == 1){ + if (use_srcport_for_path_generation == 1){ std::cout << "~" << (Dublin.srcport() + npaths - 1); } std::cout << " to " << Dublin.dst() << ":" << Dublin.dstport(); - if(use_srcport_for_path_generation == 0){ + if (use_srcport_for_path_generation == 0){ std::cout << "~" << (Dublin.dstport() + npaths - 1); } + if (interface != "") { + std::cout << " through interface " << interface; + } else { + std::cout << " through default interface"; + } std::cout << " (probing " << npaths << " path" << (npaths == 1 ? "" : "s") << ", min TTL is " << min_ttl diff --git a/src/udpv4probe.cc b/src/udpv4probe.cc index 6939bd6..5fba32f 100644 --- a/src/udpv4probe.cc +++ b/src/udpv4probe.cc @@ -55,12 +55,15 @@ IP* UDPv4Probe::forge() { } IP &UDPv4Probe::send() { - NetworkInterface iface = NetworkInterface::default_interface(); + std::string ifname = NetworkInterface::default_interface().name(); + if (interface_ != "") { + ifname = interface_; + } PacketSender sender; if (packet == nullptr) { packet = forge(); } - sender.send(*packet, iface.name()); + sender.send(*packet, ifname); return *packet; } diff --git a/tests/src/udpv4.cxx b/tests/src/udpv4.cxx index c2e6958..4b9a581 100644 --- a/tests/src/udpv4.cxx +++ b/tests/src/udpv4.cxx @@ -12,7 +12,7 @@ class UDPv4Test: public ::testing::Test { }; TEST_F(UDPv4Test, TestUDPv4Constructor) { - UDPv4Probe p = UDPv4Probe(IPv4Address("8.8.8.8"), 33434, 12345, 64, IPv4Address("127.0.0.2")); + UDPv4Probe p = UDPv4Probe(IPv4Address("8.8.8.8"), 33434, 12345, 64, "", IPv4Address("127.0.0.2")); ASSERT_EQ(p.local_port(), 12345); ASSERT_EQ(p.remote_port(), 33434); ASSERT_EQ(p.ttl(), 64); @@ -30,7 +30,7 @@ TEST_F(UDPv4Test, TestUDPv4ConstructorDefaultLocalAddr) { } TEST_F(UDPv4Test, TestUDPv4PacketForging) { - UDPv4Probe p = UDPv4Probe(IPv4Address("127.0.0.3"), 33434, 12345, 64, IPv4Address("127.0.0.2")); + UDPv4Probe p = UDPv4Probe(IPv4Address("127.0.0.3"), 33434, 12345, 64, "", IPv4Address("127.0.0.2")); IP* ip = p.forge(); ASSERT_EQ(ip->tos(), 0); ASSERT_EQ(ip->id(), 60794);