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

Ipv6rebased #309

Open
wants to merge 86 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
6d65f1d
Use INET_ADDRSTRLEN instead of hardcoding it
bastien-roucaries Apr 4, 2020
4c73258
Let IPs resolve using getaddrinfo
khorben Jun 12, 2018
94bed23
Factorize IP resolution between http and https
bastien-roucaries Apr 4, 2020
03e1c20
Be more consistent when creating ~/.fwknoprc
khorben Jun 12, 2018
de84936
Improve IPV4 min length by using strlen
bastien-roucaries Apr 4, 2020
2dc902b
Let IPs resolve to IPv6 addresses
khorben Jun 12, 2018
5d8e6cf
Allow ipv6 for resolving url
bastien-roucaries Apr 4, 2020
0ab6173
Let IPs resolve to IPv6 addresses
khorben Jun 12, 2018
5a53b3b
Also catch the IPv6 version of INADDR_ANY
khorben Jun 12, 2018
8cc8908
Migrate is_valid_ipv4_addr() to a more generic function
khorben Jun 12, 2018
2754326
Implement is_valid_ip_addr() with getaddrinfo()
khorben Jun 12, 2018
22aa677
Give have_allow_ip() a chance to allow IPv6
khorben Jun 12, 2018
d5ef047
Allow connecting to remote IPv6 hosts for TCP or UDP
khorben Jun 14, 2018
a8aa02d
Use uppercase to log "IP"
khorben Jun 14, 2018
cef18b7
Also check for <netinet/ip6.h> and <netinet/icmp6.h>
khorben Jun 14, 2018
43dc125
Rework the network listening routine
khorben Jun 15, 2018
508c9f3
Rework the network listening routine some more
khorben Jun 15, 2018
47f2309
Code cleanup
khorben Jun 15, 2018
00a4914
Also include <netinet/ip6.h> where relevant
khorben Jun 15, 2018
9b9af40
Protect some more headers for inclusion
khorben Jun 15, 2018
c69c44e
Add support for receiving SPA messages over IPv6
khorben Jun 15, 2018
73de567
Interpret incoming addresses according to their family
khorben Jun 26, 2018
1dc74a1
Let access list stanzas be defined in IPv6
khorben Jun 26, 2018
b3ea4ab
Typo
khorben Jun 26, 2018
43d1b4a
Typo
khorben Jun 26, 2018
429ad67
Constify
khorben Jul 9, 2018
f2db271
Use a more appropriate type for sd_len
khorben Jul 9, 2018
c489d83
Allow access control "ANY" with any protocol family
khorben Jul 9, 2018
65cbaf5
Use AF_INET instead of PF_INET
khorben Jul 9, 2018
b846b35
Use sizeof() instead of re-using hard-coded values
khorben Jul 9, 2018
a4e25b2
Use sizeof() instead of re-using hard-coded values
khorben Jul 9, 2018
b1e637b
Use a constant for AF_INET
khorben Jul 9, 2018
f6bc375
Use /usr/bin/env to locate perl
khorben Jul 10, 2018
4aac32d
Rework IPv6 support when comparing addresses
khorben Jul 10, 2018
f3a2e8d
Fix processing command-line arguments with whitespace
khorben Jul 10, 2018
f956217
Set the address family for incoming SPA over UDP
khorben Jul 10, 2018
8f64afb
Specify the family at run-time for TCP/UDP servers
khorben Jul 10, 2018
7dfe143
Add IPv6 support to the plain UDP and TCP servers
khorben Jul 10, 2018
b18c82c
Constify
khorben Jul 17, 2018
2170845
Terminate IPs resolved externally as expected
khorben Jul 17, 2018
e23c081
Prepare access stanzas for more address families
khorben Jul 18, 2018
885ac36
Use the correct offset for inet_ntop()
khorben Jul 18, 2018
0fe28e5
Simplify the calculation of pkt_data_len
khorben Jul 18, 2018
fa5a2a5
Correct the packet length calculation with IPv6
khorben Jul 18, 2018
9ae3f8d
Fix some issues with TCP over IPv6
khorben Jul 18, 2018
776c7ea
Begin to allow IPv6 addresses in source stanzas
khorben Jul 24, 2018
b17288a
Add a command-line option to enable IPv6 (TCP/UDP)
khorben Jul 27, 2018
e2dad97
Optimize moot variable initialization away
khorben Jul 27, 2018
3cb8025
Fix the build on Linux (iptables)
khorben Jul 27, 2018
dd927b3
Fix the build with firewalld
khorben Jul 27, 2018
2157346
Update the manual page for the -6 option (--ipv6)
khorben Jul 30, 2018
5a24a63
Support further address families in the future
khorben Aug 6, 2018
cb3aa68
Verify if the protocol family matches incoming packets
khorben Aug 6, 2018
f3db1b3
Do not use INADDR_ANY for default ports
khorben Aug 6, 2018
e90822b
Check for errors from inet_addr() with INADDR_NONE
khorben Aug 6, 2018
6ce6464
Fix build with NFQ enabled
khorben Aug 7, 2018
c2703e4
Allow the longest possible IPv6 address in sources
khorben Aug 7, 2018
38d7931
Add a configuration variable for IPv6 firewall binaries
khorben Aug 8, 2018
021c6b4
Add the fw_command6 member to the right struct fw_config
khorben Aug 8, 2018
972b2e7
Initialize the configuration for ip6tables as well
khorben Aug 8, 2018
50661f6
Add IPv6 support to --fw-list{,all}
khorben Aug 8, 2018
5784487
Update a comment
khorben Aug 8, 2018
7217e45
Add preliminary support for IPv6 with iptables
khorben Aug 8, 2018
ff4ea85
Code cleanup
khorben Aug 8, 2018
6cbe8f3
Fix a couple more uses of ctype(3)
khorben Aug 8, 2018
da6f1c9
Provide enough space to resolve IPv6 addresses
khorben Aug 8, 2018
98b367a
Remove support for IPv6 for rules shared with IPv4
khorben Aug 8, 2018
4369eea
Add support for rule expiration with IPv6
khorben Aug 8, 2018
c899fcb
Revert "Remove support for IPv6 for rules shared with IPv4"
khorben Aug 8, 2018
fc5d908
Code cleanup
khorben Aug 12, 2018
a8c8a0d
Default to IPv6 rules when listening on IPv6
khorben Aug 12, 2018
9ae09ed
Remove useless code
khorben Aug 12, 2018
2ff082c
Resolve hostnames to IPv6 addresses in IPv6 mode
khorben Aug 12, 2018
1a020c6
Re-indent
khorben Aug 12, 2018
9633a26
Only support IPv4 on Windows
khorben Aug 12, 2018
f1b8181
Code cleanup
khorben Aug 12, 2018
d83e45a
Use "::" for matching any address for IPv6 rules
khorben Aug 15, 2018
7929e3a
No longer accept colon (":") as port separator
khorben Aug 15, 2018
09b520b
Fix DNAT with IPv6
khorben Aug 15, 2018
c3db6be
Use "::/0" for IPT_ANY_IPV6
khorben Aug 16, 2018
0d28bae
Port src_dst_check() to IPv6
khorben Aug 16, 2018
a9ed5d6
Also output the value obtained for ip6tables
khorben Aug 22, 2018
26c1da6
Complete the check and search for ip6tables
khorben Aug 24, 2018
040459d
[test suite] start on IPv6 tests
mrash Sep 2, 2018
9c5069e
[test suite] first working IPv6 complete cycle test
mrash Sep 2, 2018
2f98e06
add IPv6 UDP server test, and IPv6 invalid destination test
mrash Oct 20, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions android/project/jni/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
/* Path to firewall command executable (it should match the firewall type). */
#define FIREWALL_EXE "/sbin/iptables"

/* Path to firewall command executable for IPv6 (it should match the firewall type). */
#define FIREWALL_EXE_IPV6 "/sbin/ip6tables"

/* The firewall type: ipf. */
/* #undef FIREWALL_IPF */

Expand Down
13 changes: 7 additions & 6 deletions client/config_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -871,9 +871,9 @@ create_fwknoprc(const char *rcfile)
"#FW_TIMEOUT 30\n"
"#SPA_SERVER_PORT 62201\n"
"#SPA_SERVER_PROTO udp\n"
"#ALLOW_IP <ip addr>\n"
"#ALLOW_IP <IP address>\n"
"#SPOOF_USER <username>\n"
"#SPOOF_SOURCE_IP <IPaddr>\n"
"#SPOOF_SOURCE_IP <IP address>\n"
"#TIME_OFFSET 0\n"
"#USE_GPG N\n"
"#GPG_HOMEDIR /path/to/.gnupg\n"
Expand Down Expand Up @@ -986,7 +986,7 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val)
else /* Assume IP address and validate */
{
strlcpy(options->allow_ip_str, val, sizeof(options->allow_ip_str));
if(! is_valid_ipv4_addr(options->allow_ip_str, strlen(options->allow_ip_str)))
if(! is_valid_ip_addr(options->allow_ip_str, strlen(options->allow_ip_str), AF_INET))
parse_error = -1;
}
}
Expand Down Expand Up @@ -1850,7 +1850,8 @@ validate_options(fko_cli_options_t *options)
exit(EXIT_FAILURE);
}
else if(options->verbose
&& strncmp(options->allow_ip_str, "0.0.0.0", strlen("0.0.0.0")) == 0)
&& (strncmp(options->allow_ip_str, "0.0.0.0", strlen("0.0.0.0")) == 0
|| strncmp(options->allow_ip_str, "::", strlen("::")) == 0))
{
log_msg(LOG_VERBOSITY_WARNING,
"[-] WARNING: Should use -a or -R to harden SPA against potential MITM attacks");
Expand All @@ -1865,7 +1866,7 @@ validate_options(fko_cli_options_t *options)
{
options->resolve_ip_http_https = 0;

if(! is_valid_ipv4_addr(options->allow_ip_str, strlen(options->allow_ip_str)))
if(! is_valid_ip_addr(options->allow_ip_str, strlen(options->allow_ip_str), AF_UNSPEC))
{
log_msg(LOG_VERBOSITY_ERROR,
"Invalid allow IP specified for SPA access");
Expand All @@ -1875,7 +1876,7 @@ validate_options(fko_cli_options_t *options)

if (options->spoof_ip_src_str[0] != 0x00)
{
if(! is_valid_ipv4_addr(options->spoof_ip_src_str, strlen(options->spoof_ip_src_str)))
if(! is_valid_ip_addr(options->spoof_ip_src_str, strlen(options->spoof_ip_src_str), AF_UNSPEC))
{
log_msg(LOG_VERBOSITY_ERROR, "Invalid spoof IP");
exit(EXIT_FAILURE);
Expand Down
8 changes: 1 addition & 7 deletions client/fwknop.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,12 +774,6 @@ set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options, const char * const acc

if (nat_access_buf[0] == 0x0 && options->nat_access_str[0] != 0x0)
{
/* Force the ':' (if any) to a ','
*/
ndx = strchr(options->nat_access_str, ':');
if (ndx != NULL)
*ndx = ',';

ndx = strchr(options->nat_access_str, ',');
if (ndx != NULL)
{
Expand Down Expand Up @@ -820,7 +814,7 @@ set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options, const char * const acc
}


if (is_valid_ipv4_addr(options->nat_access_str, hostlen) || is_valid_hostname(options->nat_access_str, hostlen))
if (is_valid_ip_addr(options->nat_access_str, hostlen, AF_UNSPEC) || is_valid_hostname(options->nat_access_str, hostlen))
{
snprintf(nat_access_buf, MAX_LINE_LEN, NAT_ACCESS_STR_TEMPLATE,
options->nat_access_str, access_port);
Expand Down
4 changes: 2 additions & 2 deletions client/fwknop_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ typedef struct fko_cli_options
int no_save_args;
int use_hmac;
char spa_server_str[MAX_SERVER_STR_LEN]; /* may be a hostname */
char allow_ip_str[MAX_IPV4_STR_LEN];
char spoof_ip_src_str[MAX_IPV4_STR_LEN];
char allow_ip_str[MAX_IPV46_STR_LEN];
char spoof_ip_src_str[MAX_IPV46_STR_LEN];
char spoof_user[MAX_USERNAME_LEN];
int rand_port;
char gpg_recipient_key[MAX_GPG_KEY_ID];
Expand Down
126 changes: 55 additions & 71 deletions client/http_resolve_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,46 @@ struct url
char path[MAX_URL_PATH_LEN+1];
};

static int resolve_ip(const char * resp, fko_cli_options_t *options, const char * extraerror1,char *extraerror2) {
struct addrinfo *result=NULL;
struct addrinfo *rp;
struct addrinfo hints;
int error;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST | AI_CANONNAME;
error = getaddrinfo(resp, NULL, &hints, &result);
if (error != 0)
{
log_msg(LOG_VERBOSITY_ERROR,
"[-] Could not resolve IP via: '%s%s'", extraerror1, extraerror2);
return(-1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor issue: wrong indentation from here to the end of the function.
Also, to stay aligned with the global style, it is 4 spaces and not 2 for this whole function.

/* get last IP in case of multi IP host */
for (rp = result; rp != NULL; rp = rp->ai_next) {
/* the canonical value is in the first structure returned */
strlcpy(options->allow_ip_str,
rp->ai_canonname, sizeof(options->allow_ip_str));
break;
}
freeaddrinfo(result);

log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via '%s%s') as: %s",
extraerror1,extraerror2, options->allow_ip_str);
return 1;
}

static int
try_url(struct url *url, fko_cli_options_t *options)
{
int sock=-1, sock_success=0, res, error, http_buf_len, i;
int sock=-1, sock_success=0, i, res, error, http_buf_len;
int bytes_read = 0, position = 0;
int o1, o2, o3, o4;
struct addrinfo *result=NULL, *rp, hints;
char http_buf[HTTP_MAX_REQUEST_LEN] = {0};
char http_response[HTTP_MAX_RESPONSE_LEN] = {0};
char *ndx;
char *ndx, c;

#ifdef WIN32
WSADATA wsa_data;
Expand All @@ -91,13 +121,6 @@ try_url(struct url *url, fko_cli_options_t *options)
);

http_buf_len = strlen(http_buf);

memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

#if AFL_FUZZING
/* Make sure to not generate any resolution requests when compiled
* for AFL fuzzing cycles
Expand All @@ -111,6 +134,10 @@ try_url(struct url *url, fko_cli_options_t *options)
return(1);
#endif

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(url->host, url->port, &hints, &result);
if (error != 0)
{
Expand Down Expand Up @@ -198,44 +225,19 @@ try_url(struct url *url, fko_cli_options_t *options)
ndx += 4;

/* Walk along the content to try to find the end of the IP address.
* Note: We are expecting the content to be just an IP address
* (possibly followed by whitespace or other not-digit value).
*/
for(i=0; i<MAX_IPV4_STR_LEN; i++) {
if(! isdigit((int)(unsigned char)*(ndx+i)) && *(ndx+i) != '.')
break;
}

* Note: We are expecting the content to be just an IP address
* (possibly followed by whitespace or other not-digit value).
*/
for(i=0; i<MAX_IPV46_STR_LEN; i++) {
c = *(ndx+i);
if(! isdigit((int)(unsigned char)c) && ! ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) && c != '.' && c != ':')
break;
}
/* Terminate at the first non-digit and non-dot.
*/
*(ndx+i) = '\0';

/* Now that we have what we think is an IP address string. We make
* sure the format and values are sane.
*/
if((sscanf(ndx, "%u.%u.%u.%u", &o1, &o2, &o3, &o4)) == 4
&& o1 >= 0 && o1 <= 255
&& o2 >= 0 && o2 <= 255
&& o3 >= 0 && o3 <= 255
&& o4 >= 0 && o4 <= 255)
{
strlcpy(options->allow_ip_str, ndx, sizeof(options->allow_ip_str));

log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via http://%s%s) as: %s",
url->host,
url->path,
options->allow_ip_str);
*(ndx+i) = '\0';

return(1);
}
else
{
log_msg(LOG_VERBOSITY_ERROR,
"[-] From http://%s%s\n Invalid IP (%s) in HTTP response:\n\n%s",
url->host, url->path, ndx, http_response);
return(-1);
}
return resolve_ip(ndx,options,url->host,url->path);
}

static int
Expand Down Expand Up @@ -323,8 +325,8 @@ parse_url(char *res_url, struct url* url)
int
resolve_ip_https(fko_cli_options_t *options)
{
int o1, o2, o3, o4, got_resp=0, i=0;
char *ndx, resp[MAX_IPV4_STR_LEN+1] = {0};
int got_resp=0;
char resp[MAX_IPV46_STR_LEN+1] = {0};
struct url url; /* for validation only */
char wget_ssl_cmd[MAX_URL_PATH_LEN] = {0}; /* for verbose logging only */

Expand Down Expand Up @@ -493,32 +495,14 @@ resolve_ip_https(fko_cli_options_t *options)
pclose(wget);
#endif

if(got_resp)
if(! got_resp)
{
ndx = resp;
for(i=0; i<MAX_IPV4_STR_LEN; i++) {
if(! isdigit((int)(unsigned char)*(ndx+i)) && *(ndx+i) != '.')
break;
}
*(ndx+i) = '\0';

if((sscanf(ndx, "%u.%u.%u.%u", &o1, &o2, &o3, &o4)) == 4
&& o1 >= 0 && o1 <= 255
&& o2 >= 0 && o2 <= 255
&& o3 >= 0 && o3 <= 255
&& o4 >= 0 && o4 <= 255)
{
strlcpy(options->allow_ip_str, ndx, sizeof(options->allow_ip_str));

log_msg(LOG_VERBOSITY_INFO,
"\n[+] Resolved external IP (via '%s') as: %s",
wget_ssl_cmd, options->allow_ip_str);
return 1;
}
log_msg(LOG_VERBOSITY_ERROR,
"[-] Could not resolve IP via: '%s'", wget_ssl_cmd);
return -1;
}
log_msg(LOG_VERBOSITY_ERROR,
"[-] Could not resolve IP via: '%s'", wget_ssl_cmd);
return -1;

return resolve_ip(resp,options,wget_ssl_cmd,"");
}

int
Expand Down
Loading