Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142647088
D18908.id61029.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D18908.id61029.diff
View Options
Index: lib/libfetch/common.h
===================================================================
--- lib/libfetch/common.h
+++ lib/libfetch/common.h
@@ -70,12 +70,47 @@
const char *string;
};
+/* For SOCKS header size */
+#define HEAD_SIZE 4
+#define FQDN_SIZE 256
+#define PACK_SIZE 1
+#define PORT_SIZE 2
+#define BUFF_SIZE HEAD_SIZE + FQDN_SIZE + PACK_SIZE + PORT_SIZE
+
+/* SOCKS5 Request Header */
+#define SOCKS_VERSION_5 0x05
+/* SOCKS5 CMD */
+#define SOCKS_CONNECTION 0x01
+#define SOCKS_BIND 0x02
+#define SOCKS_UDP 0x03
+#define SOCKS_NOMETHODS 0xFF
+#define SOCKS5_NOTIMPLEMENTED 0x00
+/* SOCKS5 Reserved */
+#define SOCKS_RSV 0x00
+/* SOCKS5 Address Type */
+#define SOCKS_ATYP_IPV4 0x01
+#define SOCKS_ATYP_DOMAINNAME 0x03
+#define SOCKS_ATYP_IPV6 0x04
+/* SOCKS5 Reply Field */
+#define SOCKS_SUCCESS 0x00
+#define SOCKS_GENERAL_FAILURE 0x01
+#define SOCKS_CONNECTION_NOT_ALLOWED 0x02
+#define SOCKS_NETWORK_UNREACHABLE 0x03
+#define SOCKS_HOST_UNREACHABLE 0x04
+#define SOCKS_CONNECTION_REFUSED 0x05
+#define SOCKS_TTL_EXPIRED 0x06
+#define SOCKS_COMMAND_NOT_SUPPORTED 0x07
+#define SOCKS_ADDRESS_NOT_SUPPORTED 0x08
+
/* for fetch_writev */
struct iovec;
void fetch_seterr(struct fetcherr *, int);
void fetch_syserr(void);
void fetch_info(const char *, ...) __printflike(1, 2);
+int fetch_socks5_getenv(char **host, int *port);
+int fetch_socks5_init(conn_t *conn, const char *host,
+ int port, int verbose);
int fetch_default_port(const char *);
int fetch_default_proxy_port(const char *);
struct addrinfo *fetch_resolve(const char *, int, int);
Index: lib/libfetch/common.c
===================================================================
--- lib/libfetch/common.c
+++ lib/libfetch/common.c
@@ -42,6 +42,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <netdb.h>
#include <poll.h>
#include <pwd.h>
@@ -314,7 +315,6 @@
}
-
/*
* Bind a socket to a specific local address
*/
@@ -336,6 +336,191 @@
}
+/*
+ * SOCKS5 connection initiation, based on RFC 1928
+ * Default DNS resolution over SOCKS5
+ */
+int
+fetch_socks5_init(conn_t *conn, const char *host, int port, int verbose)
+{
+ /*
+ * Size is based on largest packet prefix (4 bytes) +
+ * Largest FQDN (256) + one byte size (1) +
+ * Port (2)
+ */
+ unsigned char buf[BUFF_SIZE];
+ unsigned char *ptr;
+
+ if (verbose)
+ fetch_info("Initializing SOCKS5 connection: %s:%d", host, port);
+
+ /* Connection initialization */
+ ptr = buf;
+ *ptr++ = SOCKS_VERSION_5;
+ *ptr++ = SOCKS_CONNECTION;
+ *ptr++ = SOCKS_RSV;
+
+ if (fetch_write(conn, buf, 3) != 3) {
+ fprintf(stderr, "SOCKS5: Failed to send selection method.\n");
+ goto fail;
+ }
+
+ /* Verify response from SOCKS5 server */
+ if (fetch_read(conn, buf, 2) != 2) {
+ fprintf(stderr, "SOCKS5: Failed to read method.\n");
+ goto fail;
+ }
+
+ ptr = buf;
+ if (ptr[0] != SOCKS_VERSION_5) {
+ fprintf(stderr, "SOCKS5: Currently only version 5 is implemented.\n");
+ goto fail;
+ }
+ if (ptr[1] == SOCKS_NOMETHODS) {
+ fprintf(stderr, "SOCKS5: No acceptable methods. Disconnecting.\n");
+ goto fail;
+ }
+ else if (ptr[1] != SOCKS5_NOTIMPLEMENTED) {
+ fprintf(stderr, "SOCKS5: Method currently not implemented. Disconnecting.\n");
+ goto fail;
+ }
+
+ /* Send Request */
+ *ptr++ = SOCKS_VERSION_5;
+ *ptr++ = SOCKS_CONNECTION;
+ *ptr++ = SOCKS_RSV;
+ /* Encode all targets as a hostname to avoid DNS leaks */
+ *ptr++ = SOCKS_ATYP_DOMAINNAME;
+ if (strlen(host) > FQDN_SIZE) {
+ fprintf(stderr, "Hostname above 256 bytes, exiting.\n");
+ goto fail;
+ }
+ *ptr++ = strlen(host);
+ strncpy(ptr, host, strlen(host));
+ ptr = ptr + strlen(host);
+
+ port = htons(port);
+ *ptr++ = port & 0x00ff;
+ *ptr++ = (port & 0xff00) >> 8;
+
+ if (fetch_write(conn, buf, ptr - buf) != ptr - buf) {
+ fprintf(stderr, "SOCKS5: Failed to request.\n");
+ goto fail;
+ }
+
+ /* BND.ADDR is variable length, read the largest on non-blocking socket */
+ if (!fetch_read(conn, buf, BUFF_SIZE)) {
+ fprintf(stderr, "SOCKS5: Failed to receive reply.\n");
+ goto fail;
+ }
+
+ ptr = buf;
+ if (*ptr++ != SOCKS_VERSION_5) {
+ fprintf(stderr, "SOCKS5: Server responded with a non-version 5 response.\n");
+ goto fail;
+ }
+
+ switch(*ptr++) {
+ case SOCKS_SUCCESS:
+ break;
+ case SOCKS_GENERAL_FAILURE:
+ fprintf(stderr, "SOCKS5: General server failure\n");
+ goto fail;
+ case SOCKS_CONNECTION_NOT_ALLOWED:
+ fprintf(stderr, "SOCKS5: Connection not allowed by ruleset.\n");
+ goto fail;
+ case SOCKS_NETWORK_UNREACHABLE:
+ fprintf(stderr, "SOCKS5: Network unreachable.\n");
+ goto fail;
+ case SOCKS_HOST_UNREACHABLE:
+ fprintf(stderr, "SOCKS5: Host unreachable.\n");
+ goto fail;
+ case SOCKS_CONNECTION_REFUSED:
+ fprintf(stderr, "SOCKS5: Connection refused.\n");
+ goto fail;
+ case SOCKS_TTL_EXPIRED:
+ fprintf(stderr, "SOCKS5: TTL expired.\n");
+ goto fail;
+ case SOCKS_COMMAND_NOT_SUPPORTED:
+ fprintf(stderr, "SOCKS5: Command not supported.\n");
+ goto fail;
+ case SOCKS_ADDRESS_NOT_SUPPORTED:
+ fprintf(stderr, "SOCKS5: Address type not supported.\n");
+ goto fail;
+ default:
+ fprintf(stderr, "SOCKS5: Unspecified failure.\n");
+ goto fail;
+ }
+
+ return (1);
+
+fail:
+ return (0);
+}
+
+/*
+ * Perform SOCKS5 initialization
+ */
+int
+fetch_socks5_getenv(char **host, int *port)
+{
+ char *socks5env, *endptr, *ext;
+
+ if ((socks5env = getenv("SOCKS5_PROXY")) == NULL || *socks5env == '\0') {
+ *host = NULL;
+ *port = -1;
+ return (-1);
+ }
+
+ /* IPv6 addresses begin and end in brackets */
+ if (socks5env[0] == '[') {
+ if (socks5env[strlen(socks5env) - 1] == ']') {
+ *host = strndup(socks5env, strlen(socks5env));
+ if (*host == NULL)
+ goto fail;
+ *port = 1080; /* Default port as defined in RFC1928 */
+ } else {
+ ext = strstr(socks5env, "]:");
+ if (ext == NULL) {
+ fprintf(stderr, "Bad SOCKS5_PROXY format, missing closing ']': %s\n",
+ socks5env);
+ return (0);
+ }
+ ext=ext+1;
+ *host = strndup(socks5env, ext - socks5env);
+ if (*host == NULL)
+ goto fail;
+ *port = strtoimax(ext + 1, (char **)&endptr, 10);
+ if (*port == 0 && errno == EINVAL) {
+ fprintf(stderr, "Bad SOCKS5_PROXY port: %s\n", socks5env);
+ return (0);
+ }
+ }
+ } else {
+ ext = strrchr(socks5env, ':');
+ if (ext == NULL) {
+ *host = strdup(socks5env);
+ *port = 1080;
+ } else {
+ *host = strndup(socks5env, ext-socks5env);
+ if (*host == NULL)
+ goto fail;
+ *port = strtoimax(ext + 1, (char **)&endptr, 10);
+ if (*port == 0 && errno == EINVAL) {
+ fprintf(stderr, "Bad SOCKS5_PROXY port: %s\n", socks5env);
+ return (0);
+ }
+ }
+ }
+
+ return (2);
+
+fail:
+ fprintf(stderr, "Failure to allocate memory, exiting.\n");
+ return (-1);
+}
+
+
/*
* Establish a TCP connection to the specified port on the specified host.
*/
@@ -346,22 +531,38 @@
const char *bindaddr;
conn_t *conn = NULL;
int err = 0, sd = -1;
+ char *sockshost;
+ int socksport;
DEBUGF("---> %s:%d\n", host, port);
- /* resolve server address */
- if (verbose)
- fetch_info("resolving server address: %s:%d", host, port);
- if ((sais = fetch_resolve(host, port, af)) == NULL)
+ /* Check if SOCKS5_PROXY env variable is set */
+ if(!fetch_socks5_getenv(&sockshost, &socksport))
goto fail;
- /* resolve client address */
- bindaddr = getenv("FETCH_BIND_ADDRESS");
- if (bindaddr != NULL && *bindaddr != '\0') {
+ /* Not using SOCKS5 proxy */
+ if (sockshost == NULL) {
+ /* resolve server address */
if (verbose)
- fetch_info("resolving client address: %s", bindaddr);
- if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
+ fetch_info("resolving server address: %s:%d", host, port);
+ if ((sais = fetch_resolve(host, port, af)) == NULL)
goto fail;
+
+ /* resolve client address */
+ bindaddr = getenv("FETCH_BIND_ADDRESS");
+ if (bindaddr != NULL && *bindaddr != '\0') {
+ if (verbose)
+ fetch_info("resolving client address: %s", bindaddr);
+ if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
+ goto fail;
+ }
+ } else {
+ /* resolve socks5 proxy address */
+ if (verbose)
+ fetch_info("resolving SOCKS5 server address: %s:%d", sockshost, socksport);
+ if ((sais = fetch_resolve(sockshost, socksport, af)) == NULL) {
+ goto fail;
+ }
}
/* try each server address in turn */
@@ -389,13 +590,19 @@
sd = -1;
}
if (err != 0) {
- if (verbose)
+ if (verbose && sockshost == NULL)
fetch_info("failed to connect to %s:%d", host, port);
+ else if (verbose && sockshost)
+ fetch_info("failed to connect to SOCKS5 server %s:%d", sockshost, socksport);
goto syserr;
}
if ((conn = fetch_reopen(sd)) == NULL)
goto syserr;
+
+ if (sockshost)
+ if (!fetch_socks5_init(conn, host, port, verbose))
+ goto fail;
if (cais != NULL)
freeaddrinfo(cais);
if (sais != NULL)
Index: lib/libfetch/fetch.3
===================================================================
--- lib/libfetch/fetch.3
+++ lib/libfetch/fetch.3
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2016
+.Dd June 19, 2019
.Dt FETCH 3
.Os
.Sh NAME
@@ -652,6 +652,13 @@
Same as
.Ev NO_PROXY ,
for compatibility.
+.It Ev SOCKS5_PROXY
+Uses SOCKS version 5 to make connection.
+The format must be the IP or hostname followed by a colon for the port.
+IPv6 addresses must enclose the address in brackets.
+If no port is specified, the default is 1080.
+This setting will supercede a connection to an
+.Ev HTTP_PROXY .
.It Ev SSL_ALLOW_SSL3
Allow SSL version 3 when negotiating the connection (not recommended).
.It Ev SSL_CA_CERT_FILE
@@ -710,6 +717,21 @@
NO_PROXY=localhost,127.0.0.1
.Ed
.Pp
+To use a SOCKS5 proxy, set the
+.Ev SOCKS5_PROXY
+environment variable to a
+valid host or IP followed by an optional colon and the port.
+IPv6 addresses must be enclosed in brackets.
+The following are examples of valid settings:
+.Bd -literal -offset indent
+SOCKS5_PROXY=proxy.example.com
+SOCKS5_PROXY=proxy.example.com:1080
+SOCKS5_PROXY=192.0.2.0
+SOCKS5_PROXY=198.51.100.0:1080
+SOCKS5_PROXY=[2001:db8::1]
+SOCKS5_PROXY=[2001:db8::2]:1080
+.Ed
+.Pp
Access HTTPS website without any certificate verification whatsoever:
.Bd -literal -offset indent
SSL_NO_VERIFY_PEER=1
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 22, 8:19 PM (4 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27861767
Default Alt Text
D18908.id61029.diff (10 KB)
Attached To
Mode
D18908: Added SOCKS5 support to libfetch
Attached
Detach File
Event Timeline
Log In to Comment