Add --vpn (-X) flag to support sending IP pkts
When a user specifies a `-i tun0` flag for a VPN interface, this interface expects raw IP packets, not ethernet frames. The --vpn option allows you to send only IP packets to the specified interface, and also performs some hacks on the receive end to ensure we can process the results. TODO: malloc a fake ethernet header for probe_modules.process_packet (or better yet, make process_packet always take an IP packet, they all seem to be implicitly doing that anyway).
This commit is contained in:
parent
8f5e4beb01
commit
2972bbefdc
26
src/recv.c
26
src/recv.c
@ -74,13 +74,13 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
|
||||
// length of entire packet captured by libpcap
|
||||
uint32_t buflen = (uint32_t) p->caplen;
|
||||
|
||||
if ((sizeof(struct iphdr) + sizeof(struct ethhdr)) > buflen) {
|
||||
if ((sizeof(struct iphdr) + (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))) > buflen) {
|
||||
// buffer not large enough to contain ethernet
|
||||
// and ip headers. further action would overrun buf
|
||||
return;
|
||||
}
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&bytes[sizeof(struct ethhdr)];
|
||||
|
||||
struct iphdr *ip_hdr = (struct iphdr *)&bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))];
|
||||
|
||||
uint32_t src_ip = ip_hdr->saddr;
|
||||
|
||||
uint32_t validation[VALIDATE_BYTES/sizeof(uint8_t)];
|
||||
@ -88,7 +88,7 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
|
||||
// and we must calculate off potential payload message instead
|
||||
validate_gen(ip_hdr->daddr, ip_hdr->saddr, (uint8_t *)validation);
|
||||
|
||||
if (!zconf.probe_module->validate_packet(ip_hdr, buflen - sizeof(struct ethhdr),
|
||||
if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr)),
|
||||
&src_ip, validation)) {
|
||||
return;
|
||||
}
|
||||
@ -97,25 +97,35 @@ void packet_cb(u_char __attribute__((__unused__)) *user,
|
||||
|
||||
fieldset_t *fs = fs_new_fieldset();
|
||||
fs_add_ip_fields(fs, ip_hdr);
|
||||
zconf.probe_module->process_packet(bytes, buflen, fs);
|
||||
// HACK !!! FIXME !!! TODO !!! BAD BAD BAD
|
||||
// probe modules for whatever reason expect the full ethernet frame
|
||||
// in process_packet. For VPN, we only get back an IP frame
|
||||
// so we COULD malloc a fake ethernet frame and copy over this payload
|
||||
// but waaaaaaahhhh performanceeee.
|
||||
// so instead, we will ASSUME (!) that the probe module will only care about
|
||||
// the IP header, and do ip_hdr = &packet[sizeof(struct ethhdr)] the first thing
|
||||
// in their function (tcp, icmp and udp probe modules all do).
|
||||
//
|
||||
// !!!IF YOUR PROBE MODULE USES THE ETH PACKET, AND YOU USE THE --vpn OPTION, YOU _WILL_ BE OWNED!!!!
|
||||
//
|
||||
zconf.probe_module->process_packet(bytes - (zconf.send_ip_pkts * sizeof(struct ethhdr)), buflen + (zconf.send_ip_pkts * sizeof(struct ethhdr)), fs);
|
||||
fs_add_system_fields(fs, is_repeat, zsend.complete);
|
||||
int success_index = zconf.fsconf.success_index;
|
||||
assert(success_index < fs->len);
|
||||
int is_success = fs_get_uint64_by_index(fs, success_index);
|
||||
|
||||
|
||||
if (is_success) {
|
||||
zrecv.success_total++;
|
||||
if (!is_repeat) {
|
||||
zrecv.success_unique++;
|
||||
set_ip(src_ip);
|
||||
}
|
||||
if (zsend.complete) {
|
||||
if (zsend.complete) {
|
||||
zrecv.cooldown_total++;
|
||||
if (!is_repeat) {
|
||||
zrecv.cooldown_unique++;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
zrecv.failure_total++;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ int send_run(int sock)
|
||||
zconf.probe_module->print_packet(stdout, buf);
|
||||
} else {
|
||||
int l = zconf.probe_module->packet_length;
|
||||
int rc = sendto(sock, buf,
|
||||
int rc = sendto(sock, buf + zconf.send_ip_pkts*sizeof(struct ethhdr),
|
||||
l, 0,
|
||||
(struct sockaddr *)&sockaddr,
|
||||
sizeof(struct sockaddr_ll));
|
||||
|
@ -14,7 +14,7 @@
|
||||
struct state_conf zconf = {
|
||||
.log_level = LOG_INFO,
|
||||
.source_port_first = 32768, // (these are the default
|
||||
.source_port_last = 61000, // ephemeral range on Linux)
|
||||
.source_port_last = 61000, // ephemeral range on Linux)
|
||||
.output_filename = NULL,
|
||||
.blacklist_filename = NULL,
|
||||
.whitelist_filename = NULL,
|
||||
@ -36,6 +36,7 @@ struct state_conf zconf = {
|
||||
.probe_args = NULL,
|
||||
.gw_mac = {0},
|
||||
.gw_mac_set = 0,
|
||||
.send_ip_pkts = 0,
|
||||
.source_ip_first = NULL,
|
||||
.source_ip_last = NULL,
|
||||
.raw_output_fields = NULL,
|
||||
|
@ -70,7 +70,8 @@ struct state_conf {
|
||||
char *probe_args;
|
||||
char *output_args;
|
||||
macaddr_t gw_mac[IFHWADDRLEN];
|
||||
int gw_mac_set;
|
||||
int gw_mac_set;
|
||||
int send_ip_pkts;
|
||||
char *source_ip_first;
|
||||
char *source_ip_last;
|
||||
char *output_filename;
|
||||
|
@ -397,6 +397,11 @@ int main(int argc, char *argv[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (args.vpn_given) {
|
||||
zconf.send_ip_pkts = 1;
|
||||
zconf.gw_mac_set = 1;
|
||||
memset(zconf.gw_mac, 0, IFHWADDRLEN);
|
||||
}
|
||||
if (cmdline_parser_required(&args, CMDLINE_PARSER_PACKAGE) != 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
48
src/zopt.c
48
src/zopt.c
@ -54,6 +54,7 @@ const char *gengetopt_args_info_help[] = {
|
||||
" -S, --source-ip=ip|range Source address(es) for scan packets",
|
||||
" -G, --gateway-mac=addr Specify gateway MAC address",
|
||||
" -i, --interface=name Specify network interface to use",
|
||||
" -X, --vpn Sends IP packets instead of Ethernet (for VPNs)",
|
||||
"\nAdvanced options:",
|
||||
" -M, --probe-module=name Select probe module (default=`tcp_synscan')",
|
||||
" -O, --output-module=name Select output module (default=`csv')",
|
||||
@ -137,6 +138,7 @@ void clear_given (struct gengetopt_args_info *args_info)
|
||||
args_info->source_ip_given = 0 ;
|
||||
args_info->gateway_mac_given = 0 ;
|
||||
args_info->interface_given = 0 ;
|
||||
args_info->vpn_given = 0 ;
|
||||
args_info->probe_module_given = 0 ;
|
||||
args_info->output_module_given = 0 ;
|
||||
args_info->probe_args_given = 0 ;
|
||||
@ -226,19 +228,20 @@ void init_args_info(struct gengetopt_args_info *args_info)
|
||||
args_info->source_ip_help = gengetopt_args_info_help[19] ;
|
||||
args_info->gateway_mac_help = gengetopt_args_info_help[20] ;
|
||||
args_info->interface_help = gengetopt_args_info_help[21] ;
|
||||
args_info->probe_module_help = gengetopt_args_info_help[23] ;
|
||||
args_info->output_module_help = gengetopt_args_info_help[24] ;
|
||||
args_info->probe_args_help = gengetopt_args_info_help[25] ;
|
||||
args_info->output_args_help = gengetopt_args_info_help[26] ;
|
||||
args_info->list_output_modules_help = gengetopt_args_info_help[27] ;
|
||||
args_info->list_probe_modules_help = gengetopt_args_info_help[28] ;
|
||||
args_info->list_output_fields_help = gengetopt_args_info_help[29] ;
|
||||
args_info->config_help = gengetopt_args_info_help[31] ;
|
||||
args_info->quiet_help = gengetopt_args_info_help[32] ;
|
||||
args_info->summary_help = gengetopt_args_info_help[33] ;
|
||||
args_info->verbosity_help = gengetopt_args_info_help[34] ;
|
||||
args_info->help_help = gengetopt_args_info_help[35] ;
|
||||
args_info->version_help = gengetopt_args_info_help[36] ;
|
||||
args_info->vpn_help = gengetopt_args_info_help[22] ;
|
||||
args_info->probe_module_help = gengetopt_args_info_help[24] ;
|
||||
args_info->output_module_help = gengetopt_args_info_help[25] ;
|
||||
args_info->probe_args_help = gengetopt_args_info_help[26] ;
|
||||
args_info->output_args_help = gengetopt_args_info_help[27] ;
|
||||
args_info->list_output_modules_help = gengetopt_args_info_help[28] ;
|
||||
args_info->list_probe_modules_help = gengetopt_args_info_help[29] ;
|
||||
args_info->list_output_fields_help = gengetopt_args_info_help[30] ;
|
||||
args_info->config_help = gengetopt_args_info_help[32] ;
|
||||
args_info->quiet_help = gengetopt_args_info_help[33] ;
|
||||
args_info->summary_help = gengetopt_args_info_help[34] ;
|
||||
args_info->verbosity_help = gengetopt_args_info_help[35] ;
|
||||
args_info->help_help = gengetopt_args_info_help[36] ;
|
||||
args_info->version_help = gengetopt_args_info_help[37] ;
|
||||
|
||||
}
|
||||
|
||||
@ -426,6 +429,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
|
||||
write_into_file(outfile, "gateway-mac", args_info->gateway_mac_orig, 0);
|
||||
if (args_info->interface_given)
|
||||
write_into_file(outfile, "interface", args_info->interface_orig, 0);
|
||||
if (args_info->vpn_given)
|
||||
write_into_file(outfile, "vpn", 0, 0 );
|
||||
if (args_info->probe_module_given)
|
||||
write_into_file(outfile, "probe-module", args_info->probe_module_orig, 0);
|
||||
if (args_info->output_module_given)
|
||||
@ -721,6 +726,7 @@ cmdline_parser_internal (
|
||||
{ "source-ip", 1, NULL, 'S' },
|
||||
{ "gateway-mac", 1, NULL, 'G' },
|
||||
{ "interface", 1, NULL, 'i' },
|
||||
{ "vpn", 0, NULL, 'X' },
|
||||
{ "probe-module", 1, NULL, 'M' },
|
||||
{ "output-module", 1, NULL, 'O' },
|
||||
{ "probe-args", 1, NULL, 0 },
|
||||
@ -737,7 +743,7 @@ cmdline_parser_internal (
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "p:o:b:w:f:n:N:t:r:B:c:e:T:P:ds:S:G:i:M:O:C:qgv:hV", long_options, &option_index);
|
||||
c = getopt_long (argc, argv, "p:o:b:w:f:n:N:t:r:B:c:e:T:P:ds:S:G:i:XM:O:C:qgv:hV", long_options, &option_index);
|
||||
|
||||
if (c == -1) break; /* Exit from `while (1)' loop. */
|
||||
|
||||
@ -970,6 +976,18 @@ cmdline_parser_internal (
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'X': /* Sends IP packets instead of Ethernet (for VPNs). */
|
||||
|
||||
|
||||
if (update_arg( 0 ,
|
||||
0 , &(args_info->vpn_given),
|
||||
&(local_args_info.vpn_given), optarg, 0, 0, ARG_NO,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"vpn", 'X',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
case 'M': /* Select probe module. */
|
||||
|
||||
@ -988,7 +1006,7 @@ cmdline_parser_internal (
|
||||
|
||||
if (update_arg( (void *)&(args_info->output_module_arg),
|
||||
&(args_info->output_module_orig), &(args_info->output_module_given),
|
||||
&(local_args_info.output_module_given), optarg, 0, "simple_file", ARG_STRING,
|
||||
&(local_args_info.output_module_given), optarg, 0, "csv", ARG_STRING,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"output-module", 'O',
|
||||
additional_error))
|
||||
|
@ -75,6 +75,8 @@ option "gateway-mac" G "Specify gateway MAC address"
|
||||
option "interface" i "Specify network interface to use"
|
||||
typestr="name"
|
||||
optional string
|
||||
option "vpn" X "Sends IP packets instead of Ethernet (for VPNs)"
|
||||
optional
|
||||
|
||||
section "Advanced options"
|
||||
|
||||
@ -84,7 +86,7 @@ option "probe-module" M "Select probe module"
|
||||
optional string
|
||||
option "output-module" O "Select output module"
|
||||
typestr="name"
|
||||
default="simple_file"
|
||||
default="csv"
|
||||
optional string
|
||||
option "probe-args" - "Arguments to pass to probe module"
|
||||
typestr="args"
|
||||
|
@ -92,10 +92,11 @@ struct gengetopt_args_info
|
||||
char * interface_arg; /**< @brief Specify network interface to use. */
|
||||
char * interface_orig; /**< @brief Specify network interface to use original value given at command line. */
|
||||
const char *interface_help; /**< @brief Specify network interface to use help description. */
|
||||
const char *vpn_help; /**< @brief Sends IP packets instead of Ethernet (for VPNs) help description. */
|
||||
char * probe_module_arg; /**< @brief Select probe module (default='tcp_synscan'). */
|
||||
char * probe_module_orig; /**< @brief Select probe module original value given at command line. */
|
||||
const char *probe_module_help; /**< @brief Select probe module help description. */
|
||||
char * output_module_arg; /**< @brief Select output module (default='simple_file'). */
|
||||
char * output_module_arg; /**< @brief Select output module (default='csv'). */
|
||||
char * output_module_orig; /**< @brief Select output module original value given at command line. */
|
||||
const char *output_module_help; /**< @brief Select output module help description. */
|
||||
char * probe_args_arg; /**< @brief Arguments to pass to probe module. */
|
||||
@ -137,6 +138,7 @@ struct gengetopt_args_info
|
||||
unsigned int source_ip_given ; /**< @brief Whether source-ip was given. */
|
||||
unsigned int gateway_mac_given ; /**< @brief Whether gateway-mac was given. */
|
||||
unsigned int interface_given ; /**< @brief Whether interface was given. */
|
||||
unsigned int vpn_given ; /**< @brief Whether vpn was given. */
|
||||
unsigned int probe_module_given ; /**< @brief Whether probe-module was given. */
|
||||
unsigned int output_module_given ; /**< @brief Whether output-module was given. */
|
||||
unsigned int probe_args_given ; /**< @brief Whether probe-args was given. */
|
||||
|
Loading…
Reference in New Issue
Block a user