mirror of
https://github.com/3proxy/3proxy.git
synced 2025-04-04 19:53:12 +08:00
Support HAProxy proxy v1 protocol
Some checks failed
C/C++ CI / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
Some checks failed
C/C++ CI / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
Added: -H option - expect HAProxy proxy v1 header, e.g. `proxy -H` parent ha type - send HAProxy proxy v1 header (must be last in redirection), e.g. allow * parent 1000 ha parent 1000 proxy 1.2.3.4 3128 socks
This commit is contained in:
parent
27c9e62faa
commit
89b45b1b2a
46
src/auth.c
46
src/auth.c
@ -222,6 +222,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
int weight = 1000;
|
||||
int res;
|
||||
int done = 0;
|
||||
int ha = 0;
|
||||
struct chain * cur;
|
||||
struct chain * redir = NULL;
|
||||
int r2;
|
||||
@ -278,6 +279,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
return 0;
|
||||
}
|
||||
else if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
|
||||
int i;
|
||||
if(cur->extuser){
|
||||
if(param->extusername)
|
||||
myfree(param->extusername);
|
||||
@ -289,27 +291,18 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
}
|
||||
if(*cur->extuser == '*' && !param->username) return 4;
|
||||
}
|
||||
switch(cur->type){
|
||||
case R_POP3:
|
||||
param->redirectfunc = pop3pchild;
|
||||
break;
|
||||
case R_FTP:
|
||||
param->redirectfunc = ftpprchild;
|
||||
break;
|
||||
case R_ADMIN:
|
||||
param->redirectfunc = adminchild;
|
||||
break;
|
||||
case R_SMTP:
|
||||
param->redirectfunc = smtppchild;
|
||||
break;
|
||||
case R_TLS:
|
||||
param->redirectfunc = tlsprchild;
|
||||
break;
|
||||
default:
|
||||
param->redirectfunc = proxychild;
|
||||
|
||||
for(i=0; redirs[i].name; i++){
|
||||
if(cur->type == redirs[i].redir) {
|
||||
param->redirectfunc = redirs[i].func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cur->type == R_HA){
|
||||
ha = 1;
|
||||
}
|
||||
if(cur->next)continue;
|
||||
return 0;
|
||||
if(!ha) return 0;
|
||||
}
|
||||
else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) {
|
||||
unsigned short port = *SAPORT(¶m->sinsr);
|
||||
@ -324,6 +317,21 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
|
||||
if((res = alwaysauth(param))){
|
||||
return (res >= 10)? res : 60+res;
|
||||
}
|
||||
if(ha) {
|
||||
char buf[128];
|
||||
int len;
|
||||
len = sprintf(buf, "PROXY %s ",
|
||||
*SAFAMILY(¶m->sincr) == AF_INET6 ? "TCP6" : "TCP4");
|
||||
len += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), buf+len, sizeof(param->sincr));
|
||||
buf[len++] = ' ';
|
||||
len += myinet_ntop(*SAFAMILY(¶m->sincl), SAADDR(¶m->sincl), buf+len, sizeof(param->sincl));
|
||||
len += sprintf(buf + len, " %hu %hu\r\n",
|
||||
ntohs(*SAPORT(¶m->sincr)),
|
||||
ntohs(*SAPORT(¶m->sincl))
|
||||
);
|
||||
if(socksend(param, param->remsock, (unsigned char *)buf, len, conf.timeouts[CHAIN_TO])!=len) return 39;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
res = (redir)?clientnegotiate(redir, param, (struct sockaddr *)&cur->addr, cur->exthost):0;
|
||||
|
48
src/conf.c
48
src/conf.c
@ -729,10 +729,34 @@ static int h_monitor(int argc, unsigned char **argv){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct redirdesc redirs[] = {
|
||||
{R_TCP, "tcp", tcppmchild},
|
||||
{R_CONNECT, "connect", proxychild},
|
||||
{R_SOCKS4, "socks4", sockschild},
|
||||
{R_SOCKS5, "socks5", sockschild},
|
||||
{R_HTTP, "http", proxychild},
|
||||
{R_POP3, "pop3", pop3pchild},
|
||||
{R_SMTP, "smtp", smtppchild},
|
||||
{R_FTP, "ftp", ftpprchild},
|
||||
{R_CONNECTP, "connect+", proxychild},
|
||||
{R_SOCKS4P, "socks4+", sockschild},
|
||||
{R_SOCKS5P, "socks5+", sockschild},
|
||||
{R_SOCKS4B, "socks4b", sockschild},
|
||||
{R_SOCKS5B, "socks5b", sockschild},
|
||||
{R_ADMIN, "admin", adminchild},
|
||||
{R_EXTIP, "extip", NULL},
|
||||
{R_TLS, "tls", tlsprchild},
|
||||
{R_HA, "ha", NULL},
|
||||
{R_DNS, "dns", dnsprchild},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
static int h_parent(int argc, unsigned char **argv){
|
||||
struct ace *acl = NULL;
|
||||
struct chain *chains;
|
||||
char * cidr;
|
||||
int i;
|
||||
|
||||
acl = conf.acl;
|
||||
while(acl && acl->next) acl = acl->next;
|
||||
@ -752,23 +776,13 @@ static int h_parent(int argc, unsigned char **argv){
|
||||
fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum);
|
||||
return(3);
|
||||
}
|
||||
if(!strcmp((char *)argv[2], "tcp"))chains->type = R_TCP;
|
||||
else if(!strcmp((char *)argv[2], "http"))chains->type = R_HTTP;
|
||||
else if(!strcmp((char *)argv[2], "connect"))chains->type = R_CONNECT;
|
||||
else if(!strcmp((char *)argv[2], "socks4"))chains->type = R_SOCKS4;
|
||||
else if(!strcmp((char *)argv[2], "socks5"))chains->type = R_SOCKS5;
|
||||
else if(!strcmp((char *)argv[2], "connect+"))chains->type = R_CONNECTP;
|
||||
else if(!strcmp((char *)argv[2], "socks4+"))chains->type = R_SOCKS4P;
|
||||
else if(!strcmp((char *)argv[2], "socks5+"))chains->type = R_SOCKS5P;
|
||||
else if(!strcmp((char *)argv[2], "socks4b"))chains->type = R_SOCKS4B;
|
||||
else if(!strcmp((char *)argv[2], "socks5b"))chains->type = R_SOCKS5B;
|
||||
else if(!strcmp((char *)argv[2], "pop3"))chains->type = R_POP3;
|
||||
else if(!strcmp((char *)argv[2], "tls"))chains->type = R_TLS;
|
||||
else if(!strcmp((char *)argv[2], "ftp"))chains->type = R_FTP;
|
||||
else if(!strcmp((char *)argv[2], "admin"))chains->type = R_ADMIN;
|
||||
else if(!strcmp((char *)argv[2], "extip"))chains->type = R_EXTIP;
|
||||
else if(!strcmp((char *)argv[2], "smtp"))chains->type = R_SMTP;
|
||||
else {
|
||||
for(i = 0; redirs[i].name ; i++){
|
||||
if(!strcmp((char *)argv[2], redirs[i].name)) {
|
||||
chains->type = redirs[i].redir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!redirs[i].name) {
|
||||
fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
|
||||
return(4);
|
||||
}
|
||||
|
@ -325,24 +325,12 @@ static void * ef_chain_next(struct node * node){
|
||||
}
|
||||
|
||||
static void * ef_chain_type(struct node * node){
|
||||
switch (((struct chain *)node->value) -> type) {
|
||||
case R_TCP:
|
||||
return "tcp";
|
||||
case R_CONNECT:
|
||||
return "connect";
|
||||
case R_SOCKS4:
|
||||
return "socks4";
|
||||
case R_SOCKS5:
|
||||
return "socks5";
|
||||
case R_HTTP:
|
||||
return "http";
|
||||
case R_FTP:
|
||||
return "ftp";
|
||||
case R_POP3:
|
||||
return "pop3";
|
||||
default:
|
||||
return "";
|
||||
int i;
|
||||
|
||||
for(i=0; redirs[i].name; i++){
|
||||
if(((struct chain *)node->value) -> type == redirs[i].redir) return redirs[i].name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static void * ef_chain_addr(struct node * node){
|
||||
|
@ -74,6 +74,37 @@ void * threadfunc (void *p) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(param->srv->haproxy){
|
||||
char buf[128];
|
||||
int i;
|
||||
i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, sizeof(buf)-1, '\n', conf.timeouts[STRING_S]);
|
||||
if(i > 12 && !strncasecmp(buf, "PROXY TCP", 9)){
|
||||
char *token, *token2=NULL;
|
||||
unsigned short u1=0, u2=0;
|
||||
buf[i] = 0;
|
||||
token = strchr(buf, ' ');
|
||||
if(token) token = strchr(token+1, ' ');
|
||||
if(token) token++;
|
||||
if(token) token2 = strchr(token+1, ' ');
|
||||
if(token2) {
|
||||
*token2 = 0;
|
||||
getip46(46, (unsigned char*) token, (struct sockaddr *)¶m->sincr);
|
||||
token = token2+1;
|
||||
token2 = strchr(token, ' ');
|
||||
}
|
||||
if(token2) {
|
||||
*token2 = 0;
|
||||
getip46(46, (unsigned char *) token, (struct sockaddr *)¶m->sincl);
|
||||
token = token2+1;
|
||||
token2 = strchr(token, ' ');
|
||||
}
|
||||
if(token){
|
||||
sscanf(token,"%hu%hu", &u1, &u2);
|
||||
if(u1) *SAPORT(¶m->sincr) = htons(u1);
|
||||
if(u2) *SAPORT(¶m->sincl) = htons(u1);
|
||||
}
|
||||
}
|
||||
}
|
||||
((struct clientparam *) p)->srv->pf((struct clientparam *)p);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@ -417,6 +448,9 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
case 'h':
|
||||
hostname = argv[i] + 2;
|
||||
break;
|
||||
case 'H':
|
||||
srv.haproxy=1;
|
||||
break;
|
||||
case 'c':
|
||||
srv.requirecert = 1;
|
||||
if(isdigit(argv[i][2])) srv.requirecert = atoi(argv[i]+2);
|
||||
|
@ -266,7 +266,7 @@ struct passwords {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
R_TCP,
|
||||
R_TCP = 1,
|
||||
R_CONNECT,
|
||||
R_SOCKS4,
|
||||
R_SOCKS5,
|
||||
@ -281,9 +281,20 @@ typedef enum {
|
||||
R_SOCKS5B,
|
||||
R_ADMIN,
|
||||
R_EXTIP,
|
||||
R_TLS
|
||||
R_TLS,
|
||||
R_HA,
|
||||
R_DNS
|
||||
} REDIRTYPE;
|
||||
|
||||
struct redirdesc {
|
||||
REDIRTYPE redir;
|
||||
char * name;
|
||||
void * (*func)(struct clientparam *);
|
||||
};
|
||||
|
||||
extern struct redirdesc redirs[];
|
||||
|
||||
|
||||
struct chain {
|
||||
struct chain * next;
|
||||
int type;
|
||||
@ -490,6 +501,7 @@ struct srvparam {
|
||||
int clisockopts, srvsockopts, lissockopts, cbcsockopts, cbssockopts;
|
||||
int gracetraf, gracenum, gracedelay;
|
||||
int requirecert;
|
||||
int haproxy;
|
||||
#ifdef WITHSPLICE
|
||||
int usesplice;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user