Implement proxy protocol
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
cb2752889f
commit
3e29737b44
7 changed files with 74 additions and 13 deletions
|
|
@ -147,7 +147,10 @@ list<string> Configfile::parseAsList(string str)
|
||||||
string::size_type startpos=0,endpos=0,len;
|
string::size_type startpos=0,endpos=0,len;
|
||||||
string tmpstr;
|
string tmpstr;
|
||||||
|
|
||||||
str=Configfile::parseAsString(str); //remove quotes around string
|
if (str.length())
|
||||||
|
{
|
||||||
|
str=Configfile::parseAsString(str); //remove quotes around string
|
||||||
|
}
|
||||||
|
|
||||||
len=str.length();
|
len=str.length();
|
||||||
while(startpos<len&&string::npos!=endpos)
|
while(startpos<len&&string::npos!=endpos)
|
||||||
|
|
|
||||||
|
|
@ -221,14 +221,14 @@ bool,incoming_ssl,false
|
||||||
|
|
||||||
* file with our private key (PEM format).
|
* file with our private key (PEM format).
|
||||||
* to generate, execute:
|
* to generate, execute:
|
||||||
* # openssl genrsa 1024 > private.key
|
* # openssl genrsa 2048 > hermes.key
|
||||||
string,private_key_file,"/etc/hermes/hermes.key"
|
string,private_key_file,"/etc/hermes/hermes.key"
|
||||||
|
|
||||||
* file with our server certificate (PEM format).
|
* file with our server certificate (PEM format).
|
||||||
* to generate, execute:
|
* to generate, execute:
|
||||||
* # openssl req -new -x509 -nodes -sha1 -days 365 -key private.key > certificate.crt
|
* # openssl req -new -x509 -nodes -sha1 -days 365 -key hermes.key > certificate.crt
|
||||||
* and answer the questions
|
* and answer the questions
|
||||||
string,certificate_file,"/etc/hermes/hermes.cert"
|
string,certificate_file,"/etc/hermes/certificate.crt"
|
||||||
|
|
||||||
* optional file with Diffie-Hellman parameters for Perfect Forward Secrecy.
|
* optional file with Diffie-Hellman parameters for Perfect Forward Secrecy.
|
||||||
* to generate, execute:
|
* to generate, execute:
|
||||||
|
|
@ -273,3 +273,9 @@ bool,query_spf,false
|
||||||
* You should enable this while debugging your hermes installation,
|
* You should enable this while debugging your hermes installation,
|
||||||
* as configuration errors won't be fatal.
|
* as configuration errors won't be fatal.
|
||||||
bool,return_temp_error_on_reject,false
|
bool,return_temp_error_on_reject,false
|
||||||
|
|
||||||
|
* whether to accept connections using the proxy protocol or not
|
||||||
|
* see https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt
|
||||||
|
* only version 2.0 is supported at the moment
|
||||||
|
* only IPv4 is supported
|
||||||
|
bool,proxy_protocol,false
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ void Proxy::setOutside(Socket& p_outside)
|
||||||
* TODO: fill diagram and point to website with graphical version
|
* TODO: fill diagram and point to website with graphical version
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void Proxy::run(string &peer_address)
|
void Proxy::run(const string &real_peer_address)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SPF
|
#ifdef HAVE_SPF
|
||||||
Spf spf_checker;
|
Spf spf_checker;
|
||||||
|
|
@ -44,6 +44,32 @@ void Proxy::run(string &peer_address)
|
||||||
string to="";
|
string to="";
|
||||||
string ehlostr="";
|
string ehlostr="";
|
||||||
string resolvedname="";
|
string resolvedname="";
|
||||||
|
string peer_address = "";
|
||||||
|
if (cfg.getProxyProtocol())
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
uint8_t sig[12]; /* hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A */
|
||||||
|
uint8_t ver_cmd; /* protocol version and command */
|
||||||
|
uint8_t fam; /* protocol family and address */
|
||||||
|
uint16_t len; /* number of following bytes part of the header */
|
||||||
|
} hdr_v2;
|
||||||
|
|
||||||
|
struct { /* for TCP/UDP over IPv4, len = 12 */
|
||||||
|
uint32_t src_addr;
|
||||||
|
uint32_t dst_addr;
|
||||||
|
uint16_t src_port;
|
||||||
|
uint16_t dst_port;
|
||||||
|
} ipv4_addr;
|
||||||
|
|
||||||
|
outside.readBytes(&hdr_v2, sizeof(hdr_v2));
|
||||||
|
outside.readBytes(&ipv4_addr, sizeof(ipv4_addr));
|
||||||
|
peer_address = Socket::intToIpv4Address(ipv4_addr.src_addr);
|
||||||
|
std::cout << "received proxied connection from " << peer_address << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
peer_address = real_peer_address;
|
||||||
|
}
|
||||||
unsigned char last_state=SMTP_STATE_WAIT_FOR_HELO;
|
unsigned char last_state=SMTP_STATE_WAIT_FOR_HELO;
|
||||||
long unimplemented_requests=0;
|
long unimplemented_requests=0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class Proxy
|
||||||
public:
|
public:
|
||||||
//Proxy():outside(NULL),inside(NULL){};
|
//Proxy():outside(NULL),inside(NULL){};
|
||||||
void setOutside(Socket&);
|
void setOutside(Socket&);
|
||||||
void run(string&);
|
void run(const string&);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //PROXY_H
|
#endif //PROXY_H
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
int Socket::created_sockets=0;
|
int Socket::created_sockets=0;
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
|
|
@ -60,8 +62,12 @@ Socket::Socket():fd(-1)
|
||||||
if(!ssl_ctx_server)
|
if(!ssl_ctx_server)
|
||||||
throw Exception(_("Error creating SSL context"),__FILE__,__LINE__);
|
throw Exception(_("Error creating SSL context"),__FILE__,__LINE__);
|
||||||
/* load certificate */
|
/* load certificate */
|
||||||
if(SSL_CTX_use_certificate_chain_file(ssl_ctx_server,cfg.getCertificateFile().c_str())==-1)
|
ERR_clear_error();
|
||||||
|
if(SSL_CTX_use_certificate_chain_file(ssl_ctx_server,cfg.getCertificateFile().c_str())!=1)
|
||||||
|
{
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
throw Exception(_("Error loading certificate"),__FILE__,__LINE__);
|
throw Exception(_("Error loading certificate"),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
/* load DH params */
|
/* load DH params */
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
|
|
@ -87,12 +93,21 @@ Socket::Socket():fd(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ERR_clear_error();
|
||||||
/* load private key */
|
/* load private key */
|
||||||
if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server,cfg.getPrivateKeyFile().c_str(),SSL_FILETYPE_PEM)==-1)
|
int retval = SSL_CTX_use_PrivateKey_file(ssl_ctx_server,cfg.getPrivateKeyFile().c_str(),SSL_FILETYPE_PEM);
|
||||||
|
if(retval != 1)
|
||||||
|
{
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
throw Exception(_("Error loading private key"),__FILE__,__LINE__);
|
throw Exception(_("Error loading private key"),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
/* check that private key and cert match */
|
/* check that private key and cert match */
|
||||||
if(!SSL_CTX_check_private_key(ssl_ctx_server))
|
retval = SSL_CTX_check_private_key(ssl_ctx_server);
|
||||||
|
if(retval != 1)
|
||||||
|
{
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
throw Exception(_("Private key doesn't match certificate file"),__FILE__,__LINE__);
|
throw Exception(_("Private key doesn't match certificate file"),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
//client
|
//client
|
||||||
ssl_ctx_client=NULL;
|
ssl_ctx_client=NULL;
|
||||||
|
|
@ -590,6 +605,13 @@ string Socket::resolveInverselyToString(string ip)
|
||||||
}
|
}
|
||||||
#endif //HAVE_GETADDRINFO
|
#endif //HAVE_GETADDRINFO
|
||||||
|
|
||||||
|
string Socket::intToIpv4Address(uint32_t ip)
|
||||||
|
{
|
||||||
|
struct in_addr ip_addr;
|
||||||
|
ip_addr.s_addr = ip;
|
||||||
|
return inet_ntoa(ip_addr);
|
||||||
|
}
|
||||||
|
|
||||||
int Socket::getFD()
|
int Socket::getFD()
|
||||||
{
|
{
|
||||||
return fd;
|
return fd;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ class Socket
|
||||||
bool connect(string,unsigned int);
|
bool connect(string,unsigned int);
|
||||||
int getFD();
|
int getFD();
|
||||||
static struct sockaddr resolve(string);
|
static struct sockaddr resolve(string);
|
||||||
|
static string intToIpv4Address(uint32_t);
|
||||||
static string resolveToString(string);
|
static string resolveToString(string);
|
||||||
static string resolveInverselyToString(string);
|
static string resolveInverselyToString(string);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,14 @@ string Utils::strtolower(string s)
|
||||||
*/
|
*/
|
||||||
string Utils::trim(string s)
|
string Utils::trim(string s)
|
||||||
{
|
{
|
||||||
while(isspace(s[0]))
|
if(s.length())
|
||||||
s.erase(0,1);
|
{
|
||||||
|
while(isspace(s[0]))
|
||||||
|
s.erase(0,1);
|
||||||
|
|
||||||
while(isspace(s[s.length()-1]))
|
while(isspace(s[s.length()-1]))
|
||||||
s.erase(s.length()-1,1);
|
s.erase(s.length()-1,1);
|
||||||
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue