stratum: handle proxy protocol (#196)

Implemented PROXY v2 protocol (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) so that stratum can be run behind an haproxy instance.

iptables/ipset still work if haproxy is run on local machine. if run on remote machine switch to using client_block_ipset() and periodically sync the ipset to the machine running haproxy.
haproxy must be configured with send-proxy-v2, version 1 does not work
This commit is contained in:
AltMinerNet 2018-01-22 01:18:57 +01:00 committed by Tanguy Pruvot
parent 117c7b3c9c
commit 1f9bfd006a
2 changed files with 74 additions and 9 deletions

View file

@ -8,6 +8,48 @@ bool socket_connected(YAAMP_SOCKET *s)
return s->sock > 0;
}
void socket_real_ip(YAAMP_SOCKET *s)
{
// get real ip if we are using haproxy or similar that use PROXY protocol
// https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
int size, ret;
const char v2sig[] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
do {
ret = recv(s->sock, &hdr, sizeof(hdr), MSG_PEEK);
} while (ret == -1 && errno == EINTR);
if (ret >= (16 + ntohs(hdr.v2.len)) &&
memcmp(&hdr.v2, v2sig, 12) == 0 &&
((hdr.v2.ver_cmd & 0xF0) == 0x20) &&
hdr.v2.fam == 0x11) {
// we received a proxy v2 header
inet_ntop(AF_INET, &hdr.v2.addr.ip4.src_addr, s->ip, 64);
s->port = ntohs(hdr.v2.addr.ip4.src_port);
// we need to consume the appropriate amount of data from the socket
// read the buffer without PEEK'ing so that we begin at the real data later in socket_nextjson
size = 16 + ntohs(hdr.v2.len);
do {
ret = recv(s->sock, &hdr, size, 0);
} while (ret == -1 && errno == EINTR);
return;
}
else {
// not received any proxy header
struct sockaddr_in name;
socklen_t len = sizeof(name);
memset(&name, 0, len);
int res = getpeername(s->sock, (struct sockaddr *)&name, &len);
inet_ntop(AF_INET, &name.sin_addr, s->ip, 64);
res = getsockname(s->sock, (struct sockaddr *)&name, &len);
s->port = ntohs(name.sin_port);
return;
}
}
YAAMP_SOCKET *socket_initialize(int sock)
{
YAAMP_SOCKET *s = new YAAMP_SOCKET;
@ -19,15 +61,7 @@ YAAMP_SOCKET *socket_initialize(int sock)
// yaamp_create_mutex(&s->mutex);
// pthread_mutex_lock(&s->mutex);
struct sockaddr_in name;
socklen_t len = sizeof(name);
memset(&name, 0, len);
int res = getpeername(s->sock, (struct sockaddr *)&name, &len);
inet_ntop(AF_INET, &name.sin_addr, s->ip, 64);
res = getsockname(s->sock, (struct sockaddr *)&name, &len);
s->port = ntohs(name.sin_port);
socket_real_ip(s);
return s;
}

View file

@ -18,6 +18,8 @@ struct YAAMP_SOCKET
bool socket_connected(YAAMP_SOCKET *s);
void socket_real_ip(YAAMP_SOCKET *s);
YAAMP_SOCKET *socket_initialize(int sock);
void socket_close(YAAMP_SOCKET *s);
@ -26,3 +28,32 @@ int socket_send(YAAMP_SOCKET *s, const char *format, ...);
int socket_send_raw(YAAMP_SOCKET *s, const char *buffer, int size);
static union {
struct {
char line[108];
} v1;
struct {
uint8_t sig[12];
uint8_t ver_cmd;
uint8_t fam;
uint16_t len;
union {
struct { /* for TCP/UDP over IPv4, len = 12 */
uint32_t src_addr;
uint32_t dst_addr;
uint16_t src_port;
uint16_t dst_port;
} ip4;
struct { /* for TCP/UDP over IPv6, len = 36 */
uint8_t src_addr[16];
uint8_t dst_addr[16];
uint16_t src_port;
uint16_t dst_port;
} ip6;
struct { /* for AF_UNIX sockets, len = 216 */
uint8_t src_addr[108];
uint8_t dst_addr[108];
} unx;
} addr;
} v2;
} hdr;