added the --resolve-ip-http and --user-agent command line args so the fwknop-c client can resolve the external network via http://www.cipherdyne.org/cgi/myip.cgi
git-svn-id: file:///home/mbr/svn/fwknop/trunk@121 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
+37
-9
@@ -26,7 +26,6 @@
|
||||
#include "fwknop_common.h"
|
||||
#include "config_init.h"
|
||||
#include "getopt.h"
|
||||
#include "spa_comm.h"
|
||||
#include "utils.h"
|
||||
#include "ctype.h"
|
||||
|
||||
@@ -202,16 +201,30 @@ static void
|
||||
validate_options(fko_cli_options_t *options)
|
||||
{
|
||||
/* Gotta have a Destination unless we are just testing or getting the
|
||||
* the version.
|
||||
* the version, and must use one of [-s|-R|-a].
|
||||
*/
|
||||
if (!options->test && !options->version && !options->show_last_command
|
||||
&& options->spa_server_str[0] == 0x0)
|
||||
if(!options->test && !options->version && !options->show_last_command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[*] Must use --destination unless --test mode is used\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (options->spa_server_str[0] == 0x0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[*] Must use --destination unless --test mode is used\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!options->resolve_ip_http && options->allow_ip_str[0] == 0x0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[*] Must use one of [-s|-R|-a] to specify IP for SPA access.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(options->resolve_ip_http || options->spa_proto == FKO_PROTO_HTTP)
|
||||
if (options->http_user_agent[0] == '\0')
|
||||
snprintf(options->http_user_agent, HTTP_MAX_USER_AGENT_LEN,
|
||||
"%s%s", "Fwknop/", MY_VERSION);
|
||||
|
||||
/* If we are using gpg, we must at least have the recipient set.
|
||||
*/
|
||||
if(options->use_gpg)
|
||||
@@ -250,7 +263,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
options->fw_timeout = -1;
|
||||
|
||||
while ((cmd_arg = getopt_long(argc, argv,
|
||||
"a:A:bB:C:D:f:gG:hIm:nN:p:P:qQ:rsS:TU:vV", cmd_opts, &index)) != -1) {
|
||||
"a:A:bB:C:D:f:gG:hIm:nN:p:P:qQ:rRsS:Tu:U:vV", cmd_opts, &index)) != -1) {
|
||||
|
||||
switch(cmd_arg) {
|
||||
case 'a':
|
||||
@@ -340,6 +353,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
case 'r':
|
||||
options->rand_port = 1;
|
||||
break;
|
||||
case 'R':
|
||||
options->resolve_ip_http = 1;
|
||||
break;
|
||||
case SHOW_LAST_ARGS:
|
||||
options->show_last_command = 1;
|
||||
break;
|
||||
@@ -356,6 +372,9 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
case 'T':
|
||||
options->test = 1;
|
||||
break;
|
||||
case 'u':
|
||||
strlcpy(options->http_user_agent, optarg, HTTP_MAX_USER_AGENT_LEN);
|
||||
break;
|
||||
case 'U':
|
||||
strlcpy(options->spoof_user, optarg, MAX_USERNAME_LEN);
|
||||
break;
|
||||
@@ -447,12 +466,21 @@ usage(void)
|
||||
" the outgoing SPA packet. Note: The 'tcpraw'\n"
|
||||
" and 'icmp' modes use raw sockets and thus\n"
|
||||
" require root access to run.\n"
|
||||
" -S, --source-port - Set the source port for outgoing SPA packet.\n"
|
||||
" -s, --source-ip - Tell the fwknopd server to accept whatever\n"
|
||||
" source IP the SPA packet has as the IP that\n"
|
||||
" needs access (not recommended, and the\n"
|
||||
" fwknopd server can ignore such requests).\n"
|
||||
" -S, --source-port - Set the source port for outgoing SPA packet.\n"
|
||||
" -Q, --spoof-source - Set the source IP for outgoing SPA packet.\n"
|
||||
" -R, --resolve-ip-http - Resolve the external network IP by\n"
|
||||
" connecting to the URL:\n"
|
||||
" http://"
|
||||
HTTP_RESOLVE_HOST
|
||||
HTTP_RESOLVE_URL
|
||||
"\n"
|
||||
" -u, --user-agent - Set the HTTP User-Agent for resolving the\n"
|
||||
" external IP via -R, or for sending SPA\n"
|
||||
" packets over HTTP.\n"
|
||||
" -U, --spoof-user - Set the username within outgoing SPA packet.\n"
|
||||
" -q, --quiet - Perform fwknop functions quietly.\n"
|
||||
" -G, --get-key - Load an encryption key/password from a file.\n"
|
||||
|
||||
+3
-1
@@ -77,14 +77,16 @@ static struct option cmd_opts[] =
|
||||
{"server-port", 1, NULL, 'p'},
|
||||
{"server-proto", 1, NULL, 'P'},
|
||||
{"quiet", 0, NULL, 'q'},
|
||||
{"rand-port", 0, NULL, 'r'},
|
||||
{"spoof-src", 1, NULL, 'Q'},
|
||||
{"rand-port", 0, NULL, 'r'},
|
||||
{"resolve-ip-http", 0, NULL, 'R'},
|
||||
{"show-last", 0, NULL, SHOW_LAST_ARGS},
|
||||
{"source-ip", 0, NULL, 's'},
|
||||
{"source-port", 1, NULL, 'S'},
|
||||
{"test", 0, NULL, 'T'},
|
||||
{"time-offset-plus", 1, NULL, TIME_OFFSET_PLUS},
|
||||
{"time-offset-minus", 1, NULL, TIME_OFFSET_MINUS},
|
||||
{"user-agent", 1, NULL, 'u'},
|
||||
{"spoof-user", 1, NULL, 'U'},
|
||||
{"verbose", 0, NULL, 'v'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
|
||||
+115
@@ -40,6 +40,7 @@ static int set_message_type(fko_ctx_t ctx, fko_cli_options_t *options);
|
||||
static int set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options);
|
||||
static int get_rand_port(fko_ctx_t ctx);
|
||||
static void dump_transmit_options(fko_cli_options_t *options);
|
||||
static void resolve_ip_http(fko_cli_options_t *options);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
@@ -113,6 +114,9 @@ main(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options.resolve_ip_http)
|
||||
resolve_ip_http(&options);
|
||||
|
||||
/* Set a message string by combining the allow IP and the
|
||||
* port/protocol. The fwknopd server allows no port/protocol
|
||||
* to be specified as well, so in this case append the string
|
||||
@@ -443,6 +447,117 @@ ipv4_str_has_port(char *str)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void resolve_ip_http(fko_cli_options_t *options)
|
||||
{
|
||||
int sock, res, error, http_buf_len, i;
|
||||
struct addrinfo *result, *rp, hints;
|
||||
char http_buf[HTTP_MAX_REQUEST_LEN];
|
||||
char http_response[HTTP_MAX_RESPONSE_LEN];
|
||||
char ip_str[MAX_IP_STR_LEN];
|
||||
|
||||
/* Build our HTTP request to resolve the external IP (this is similar to
|
||||
* to contacting whatismyip.org, but using a different URL).
|
||||
*/
|
||||
snprintf(http_buf, HTTP_MAX_REQUEST_LEN,
|
||||
"%s%s%s%s%s%s%s",
|
||||
"GET ",
|
||||
HTTP_RESOLVE_URL,
|
||||
" HTTP/1.0\r\nUser-Agent: ",
|
||||
options->http_user_agent,
|
||||
"\r\nAccept: */*\r\nHost: ",
|
||||
HTTP_RESOLVE_HOST,
|
||||
"\r\nConnection: Keep-Alive\r\n\r\n"
|
||||
);
|
||||
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;
|
||||
|
||||
error = getaddrinfo(HTTP_RESOLVE_HOST, "80", &hints, &result);
|
||||
if (error != 0)
|
||||
{
|
||||
fprintf(stderr, "[*] error in getaddrinfo: %s\n", gai_strerror(error));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
sock = socket(rp->ai_family, rp->ai_socktype,
|
||||
rp->ai_protocol);
|
||||
if (sock < 0)
|
||||
continue;
|
||||
|
||||
if (error = connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break; /* made it */
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
perror("[*] resolve_ip_http: Could not create socket: ");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
|
||||
res = send(sock, http_buf, http_buf_len, 0);
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] resolve_ip_http: write error: ");
|
||||
}
|
||||
else if(res != http_buf_len)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[#] Warning: bytes sent (%i) not spa data length (%i).\n",
|
||||
res, http_buf_len
|
||||
);
|
||||
}
|
||||
|
||||
res = read(sock, http_response, HTTP_MAX_RESPONSE_LEN);
|
||||
http_response[HTTP_MAX_RESPONSE_LEN-1] = '\0';
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
/* Now parse the response for the IP address (which should be at
|
||||
* the end of the string
|
||||
*/
|
||||
for (i=res-3; i >= 0; i--)
|
||||
{
|
||||
if(http_response[i] == '\n')
|
||||
break;
|
||||
if(http_response[i] != '.' && ! isdigit(http_response[i]))
|
||||
{
|
||||
fprintf(stderr, "[*] Invalid IP in HTTP response.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (i < MIN_IP_STR_LEN)
|
||||
{
|
||||
fprintf(stderr, "[*] Invalid IP in HTTP response.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
http_response[res-1] = '\0';
|
||||
|
||||
strlcpy(options->allow_ip_str,
|
||||
(http_response + i+1), (res - (i+2)));
|
||||
|
||||
printf("[+] Resolved external IP (via http://%s%s) as: %s\n",
|
||||
HTTP_RESOLVE_HOST, HTTP_RESOLVE_URL, options->allow_ip_str);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set NAT access string
|
||||
*/
|
||||
static int
|
||||
|
||||
+18
-3
@@ -97,6 +97,7 @@ enum {
|
||||
#define MAX_PORT_STR_LEN 6
|
||||
#define MAX_PROTO_STR_LEN 6
|
||||
#define MAX_IP_STR_LEN 16
|
||||
#define MIN_IP_STR_LEN 9
|
||||
#define MAX_SERVER_STR_LEN 50
|
||||
|
||||
#define MAX_LINE_LEN 1024
|
||||
@@ -104,6 +105,17 @@ enum {
|
||||
#define MAX_GPG_KEY_ID 128
|
||||
#define MAX_USERNAME_LEN 30
|
||||
|
||||
/* For resolving the allow IP via HTTP and sending SPA packets over
|
||||
* HTTP
|
||||
*/
|
||||
#define HTTP_RESOLVE_HOST "www.cipherdyne.org"
|
||||
#define HTTP_RESOLVE_URL "/cgi/myip.cgi"
|
||||
#define HTTP_MAX_REQUEST_LEN 2000
|
||||
#define HTTP_MAX_RESPONSE_LEN 2000
|
||||
#define HTTP_MAX_USER_AGENT_LEN 50
|
||||
|
||||
/* For time offset handling
|
||||
*/
|
||||
#define MAX_TIME_STR_LEN 9
|
||||
enum {
|
||||
TIME_OFFSET_SECONDS,
|
||||
@@ -112,9 +124,7 @@ enum {
|
||||
TIME_OFFSET_DAYS
|
||||
};
|
||||
|
||||
#define RAND_FILE "/dev/urandom"
|
||||
|
||||
/* fwkop client configuration parameters and values
|
||||
/* fwknop client configuration parameters and values
|
||||
*/
|
||||
typedef struct fko_cli_options
|
||||
{
|
||||
@@ -142,6 +152,11 @@ typedef struct fko_cli_options
|
||||
int nat_port;
|
||||
int nat_rand_port;
|
||||
|
||||
/* External IP resolution via HTTP
|
||||
*/
|
||||
int resolve_ip_http;
|
||||
char http_user_agent[HTTP_MAX_USER_AGENT_LEN];
|
||||
|
||||
/* SPA packet transmission port and protocol
|
||||
*/
|
||||
int spa_proto;
|
||||
|
||||
@@ -124,10 +124,6 @@ struct icmphdr
|
||||
} un;
|
||||
};
|
||||
|
||||
/* for sending SPA packets over HTTP
|
||||
*/
|
||||
#define HTTP_MAX_REQUEST_LEN 2000 /* bytes - reasonable maximum */
|
||||
|
||||
#define ICMP_ECHOREPLY 0 /* Echo Reply */
|
||||
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
|
||||
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
|
||||
|
||||
Reference in New Issue
Block a user