mirror of https://github.com/omar-polo/gmid.git
proxy: allow multiple proxy blocks, matching options and validations
as a side effect the order of the content of a server block is relaxed: options, location or proxy blocks can be put in any order.
This commit is contained in:
parent
e2f167afb3
commit
b7967bc1f6
16
gmid.c
16
gmid.c
|
@ -279,6 +279,7 @@ free_config(void)
|
|||
{
|
||||
struct vhost *h, *th;
|
||||
struct location *l, *tl;
|
||||
struct proxy *p, *tp;
|
||||
struct envlist *e, *te;
|
||||
struct alist *a, *ta;
|
||||
int v, i;
|
||||
|
@ -331,6 +332,17 @@ free_config(void)
|
|||
free(a);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
|
||||
TAILQ_REMOVE(&h->proxies, p, proxies);
|
||||
|
||||
free(p->match_proto);
|
||||
free(p->match_host);
|
||||
free(p->host);
|
||||
tls_unload_file(p->cert, p->certlen);
|
||||
tls_unload_file(p->key, p->keylen);
|
||||
free(p);
|
||||
}
|
||||
|
||||
free((char*)h->domain);
|
||||
free((char*)h->cert);
|
||||
free((char*)h->key);
|
||||
|
@ -338,10 +350,6 @@ free_config(void)
|
|||
free((char*)h->cgi);
|
||||
free((char*)h->entrypoint);
|
||||
|
||||
free(h->proxy.host);
|
||||
tls_unload_file(h->proxy.cert, h->proxy.certlen);
|
||||
tls_unload_file(h->proxy.key, h->proxy.keylen);
|
||||
|
||||
TAILQ_REMOVE(&hosts, h, vhosts);
|
||||
free(h);
|
||||
}
|
||||
|
|
10
gmid.h
10
gmid.h
|
@ -97,7 +97,12 @@ struct fcgi {
|
|||
};
|
||||
extern struct fcgi fcgi[FCGI_MAX];
|
||||
|
||||
TAILQ_HEAD(proxyhead, proxy);
|
||||
struct proxy {
|
||||
char *match_proto;
|
||||
char *match_host;
|
||||
const char *match_port;
|
||||
|
||||
char *host;
|
||||
const char *port;
|
||||
int notls;
|
||||
|
@ -107,6 +112,8 @@ struct proxy {
|
|||
size_t certlen;
|
||||
uint8_t *key;
|
||||
size_t keylen;
|
||||
|
||||
TAILQ_ENTRY(proxy) proxies;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(lochead, location);
|
||||
|
@ -163,7 +170,7 @@ struct vhost {
|
|||
struct envhead env;
|
||||
struct envhead params;
|
||||
struct aliashead aliases;
|
||||
struct proxy proxy;
|
||||
struct proxyhead proxies;
|
||||
};
|
||||
|
||||
struct etm { /* extension to mime */
|
||||
|
@ -229,6 +236,7 @@ struct client {
|
|||
|
||||
struct bufferevent *cgibev;
|
||||
|
||||
struct proxy *proxy;
|
||||
struct bufferevent *proxybev;
|
||||
struct tls *proxyctx;
|
||||
struct event proxyev;
|
||||
|
|
140
parse.y
140
parse.y
|
@ -81,6 +81,7 @@ char *symget(const char *);
|
|||
|
||||
struct vhost *new_vhost(void);
|
||||
struct location *new_location(void);
|
||||
struct proxy *new_proxy(void);
|
||||
char *ensure_absolute_path(char*);
|
||||
int check_block_code(int);
|
||||
char *check_block_fmt(char*);
|
||||
|
@ -88,6 +89,8 @@ int check_strip_no(int);
|
|||
int check_port_num(int);
|
||||
int check_prefork_num(int);
|
||||
void advance_loc(void);
|
||||
void advance_proxy(void);
|
||||
void parsehp(char *, char **, const char **, const char *);
|
||||
void only_once(const void*, const char*);
|
||||
void only_oncei(int, const char*);
|
||||
int fastcgi_conf(char *, char *, char *);
|
||||
|
@ -95,6 +98,7 @@ void add_param(char *, char *, int);
|
|||
|
||||
static struct vhost *host;
|
||||
static struct location *loc;
|
||||
static struct proxy *proxy;
|
||||
static int errors;
|
||||
|
||||
typedef struct {
|
||||
|
@ -115,13 +119,13 @@ typedef struct {
|
|||
%token CA CERT CGI CHROOT CLIENT
|
||||
%token DEFAULT
|
||||
%token ENTRYPOINT ENV
|
||||
%token FASTCGI
|
||||
%token FASTCGI FOR_HOST
|
||||
%token INCLUDE INDEX IPV6
|
||||
%token KEY
|
||||
%token LANG LOCATION LOG
|
||||
%token MAP MIME
|
||||
%token OCSP OFF ON
|
||||
%token PARAM PORT PREFORK PROTOCOLS PROXY
|
||||
%token PARAM PORT PREFORK PROTO PROTOCOLS PROXY
|
||||
%token RELAY_TO REQUIRE RETURN ROOT
|
||||
%token SERVER SPAWN STRIP
|
||||
%token TCP TOEXT TYPE
|
||||
|
@ -222,6 +226,8 @@ vhost : SERVER string {
|
|||
loc = new_location();
|
||||
TAILQ_INSERT_HEAD(&host->locations, loc, locations);
|
||||
|
||||
TAILQ_INIT(&host->proxies);
|
||||
|
||||
loc->match = xstrdup("*");
|
||||
host->domain = $2;
|
||||
|
||||
|
@ -229,15 +235,17 @@ vhost : SERVER string {
|
|||
yywarn("\"%s\" looks like punycode: you "
|
||||
"should use the decoded hostname", $2);
|
||||
}
|
||||
} '{' optnl servopts locations '}' {
|
||||
} '{' optnl servbody '}' {
|
||||
if (host->cert == NULL || host->key == NULL)
|
||||
yyerror("invalid vhost definition: %s", $2);
|
||||
}
|
||||
| error '}' { yyerror("bad server directive"); }
|
||||
;
|
||||
|
||||
servopts : /* empty */
|
||||
| servopts servopt optnl
|
||||
servbody : /* empty */
|
||||
| servbody servopt optnl
|
||||
| servbody location optnl
|
||||
| servbody proxy optnl
|
||||
;
|
||||
|
||||
servopt : ALIAS string {
|
||||
|
@ -281,12 +289,34 @@ servopt : ALIAS string {
|
|||
| PARAM string '=' string {
|
||||
add_param($2, $4, 0);
|
||||
}
|
||||
| proxy
|
||||
| locopt
|
||||
;
|
||||
|
||||
proxy : PROXY proxy_opt
|
||||
| PROXY '{' optnl proxy_opts '}'
|
||||
proxy : PROXY { advance_proxy(); }
|
||||
proxy_matches '{' optnl proxy_opts '}' {
|
||||
if (proxy->host == NULL)
|
||||
yyerror("invalid proxy block: missing `relay-to' option");
|
||||
|
||||
if ((proxy->cert == NULL && proxy->key != NULL) ||
|
||||
(proxy->cert != NULL && proxy->key == NULL))
|
||||
yyerror("invalid proxy block: missing cert or key");
|
||||
}
|
||||
;
|
||||
|
||||
proxy_matches : /* empty */
|
||||
| proxy_matches proxy_match
|
||||
;
|
||||
|
||||
proxy_match : PROTO string {
|
||||
only_once(proxy->match_proto, "proxy proto");
|
||||
free(proxy->match_proto);
|
||||
proxy->match_proto = $2;
|
||||
}
|
||||
| FOR_HOST string {
|
||||
only_once(proxy->match_host, "proxy for-host");
|
||||
free(proxy->match_host);
|
||||
parsehp($2, &proxy->match_host, &proxy->match_port, "10965");
|
||||
}
|
||||
;
|
||||
|
||||
proxy_opts : /* empty */
|
||||
|
@ -294,63 +324,41 @@ proxy_opts : /* empty */
|
|||
;
|
||||
|
||||
proxy_opt : CERT string {
|
||||
struct proxy *p = &host->proxy;
|
||||
|
||||
only_once(p->cert, "proxy cert");
|
||||
only_once(proxy->cert, "proxy cert");
|
||||
tls_unload_file(proxy->cert, proxy->certlen);
|
||||
ensure_absolute_path($2);
|
||||
p->cert = tls_load_file($2, &p->certlen, NULL);
|
||||
if (p->cert == NULL)
|
||||
proxy->cert = tls_load_file($2, &proxy->certlen, NULL);
|
||||
if (proxy->cert == NULL)
|
||||
yyerror("can't load cert %s", $2);
|
||||
free($2);
|
||||
}
|
||||
| KEY string {
|
||||
struct proxy *p = &host->proxy;
|
||||
|
||||
only_once(p->key, "proxy key");
|
||||
only_once(proxy->key, "proxy key");
|
||||
tls_unload_file(proxy->key, proxy->keylen);
|
||||
ensure_absolute_path($2);
|
||||
p->key = tls_load_file($2, &p->keylen, NULL);
|
||||
if (p->key == NULL)
|
||||
proxy->key = tls_load_file($2, &proxy->keylen, NULL);
|
||||
if (proxy->key == NULL)
|
||||
yyerror("can't load key %s", $2);
|
||||
free($2);
|
||||
}
|
||||
| PROTOCOLS string {
|
||||
struct proxy *p = &host->proxy;
|
||||
|
||||
if (tls_config_parse_protocols(&p->protocols, $2) == -1)
|
||||
if (tls_config_parse_protocols(&proxy->protocols, $2) == -1)
|
||||
yyerror("invalid protocols string \"%s\"", $2);
|
||||
free($2);
|
||||
}
|
||||
| RELAY_TO string {
|
||||
char *at;
|
||||
const char *errstr;
|
||||
struct proxy *p = &host->proxy;
|
||||
|
||||
only_once(p->host, "proxy relay-to");
|
||||
p->host = $2;
|
||||
|
||||
if ((at = strchr($2, ':')) != NULL) {
|
||||
*at++ = '\0';
|
||||
p->port = at;
|
||||
} else
|
||||
p->port = "1965";
|
||||
|
||||
strtonum(p->port, 1, UINT16_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
yyerror("proxy port is %s: %s", errstr,
|
||||
p->port);
|
||||
only_once(proxy->host, "proxy relay-to");
|
||||
free(proxy->host);
|
||||
parsehp($2, &proxy->host, &proxy->port, "1965");
|
||||
}
|
||||
| USE_TLS bool {
|
||||
host->proxy.notls = !$2;
|
||||
proxy->notls = !$2;
|
||||
}
|
||||
| VERIFYNAME bool {
|
||||
host->proxy.noverifyname = !$2;
|
||||
proxy->noverifyname = !$2;
|
||||
}
|
||||
;
|
||||
|
||||
locations : /* empty */
|
||||
| locations location optnl
|
||||
;
|
||||
|
||||
location : LOCATION { advance_loc(); } string '{' optnl locopts '}' {
|
||||
/* drop the starting '/' if any */
|
||||
if (*$3 == '/')
|
||||
|
@ -459,6 +467,7 @@ static struct keyword {
|
|||
{"entrypoint", ENTRYPOINT},
|
||||
{"env", ENV},
|
||||
{"fastcgi", FASTCGI},
|
||||
{"for-host", FOR_HOST},
|
||||
{"index", INDEX},
|
||||
{"ipv6", IPV6},
|
||||
{"key", KEY},
|
||||
|
@ -473,6 +482,7 @@ static struct keyword {
|
|||
{"param", PARAM},
|
||||
{"port", PORT},
|
||||
{"prefork", PREFORK},
|
||||
{"proto", PROTO},
|
||||
{"protocols", PROTOCOLS},
|
||||
{"proxy", PROXY},
|
||||
{"relay-to", RELAY_TO},
|
||||
|
@ -976,11 +986,7 @@ symget(const char *nam)
|
|||
struct vhost *
|
||||
new_vhost(void)
|
||||
{
|
||||
struct vhost *v;
|
||||
|
||||
v = xcalloc(1, sizeof(*v));
|
||||
v->proxy.protocols = TLS_PROTOCOLS_DEFAULT;
|
||||
return v;
|
||||
return xcalloc(1, sizeof(struct vhost));
|
||||
}
|
||||
|
||||
struct location *
|
||||
|
@ -994,6 +1000,16 @@ new_location(void)
|
|||
return l;
|
||||
}
|
||||
|
||||
struct proxy *
|
||||
new_proxy(void)
|
||||
{
|
||||
struct proxy *p;
|
||||
|
||||
p = xcalloc(1, sizeof(*p));
|
||||
p->protocols = TLS_PROTOCOLS_DEFAULT;
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
ensure_absolute_path(char *path)
|
||||
{
|
||||
|
@ -1066,6 +1082,32 @@ advance_loc(void)
|
|||
TAILQ_INSERT_TAIL(&host->locations, loc, locations);
|
||||
}
|
||||
|
||||
void
|
||||
advance_proxy(void)
|
||||
{
|
||||
proxy = new_proxy();
|
||||
TAILQ_INSERT_TAIL(&host->proxies, proxy, proxies);
|
||||
}
|
||||
|
||||
void
|
||||
parsehp(char *str, char **host, const char **port, const char *def)
|
||||
{
|
||||
char *at;
|
||||
const char *errstr;
|
||||
|
||||
*host = str;
|
||||
|
||||
if ((at = strchr(str, ':')) != NULL) {
|
||||
*at++ = '\0';
|
||||
*port = at;
|
||||
} else
|
||||
*port = def;
|
||||
|
||||
strtonum(*port, 1, UINT16_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
yyerror("port is %s: %s", errstr, *port);
|
||||
}
|
||||
|
||||
void
|
||||
only_once(const void *ptr, const char *name)
|
||||
{
|
||||
|
|
8
proxy.c
8
proxy.c
|
@ -233,7 +233,7 @@ proxy_error(struct bufferevent *bev, short error, void *d)
|
|||
static void
|
||||
proxy_enqueue_req(struct client *c)
|
||||
{
|
||||
struct proxy *p = &c->host->proxy;
|
||||
struct proxy *p = c->proxy;
|
||||
struct evbuffer *evb;
|
||||
char iribuf[GEMINI_URL_LEN];
|
||||
|
||||
|
@ -294,7 +294,7 @@ proxy_handshake(int fd, short event, void *d)
|
|||
static int
|
||||
proxy_setup_tls(struct client *c)
|
||||
{
|
||||
struct proxy *p = &c->host->proxy;
|
||||
struct proxy *p = c->proxy;
|
||||
struct tls_config *conf = NULL;
|
||||
|
||||
if ((conf = tls_config_new()) == NULL)
|
||||
|
@ -324,7 +324,7 @@ proxy_setup_tls(struct client *c)
|
|||
if (tls_configure(c->proxyctx, conf) == -1)
|
||||
goto err;
|
||||
|
||||
if (tls_connect_socket(c->proxyctx, c->pfd, c->domain) == -1)
|
||||
if (tls_connect_socket(c->proxyctx, c->pfd, p->host) == -1)
|
||||
goto err;
|
||||
|
||||
event_set(&c->proxyev, c->pfd, EV_READ|EV_WRITE, proxy_handshake, c);
|
||||
|
@ -345,7 +345,7 @@ err:
|
|||
int
|
||||
proxy_init(struct client *c)
|
||||
{
|
||||
struct proxy *p = &c->host->proxy;
|
||||
struct proxy *p = c->proxy;
|
||||
|
||||
c->type = REQUEST_PROXY;
|
||||
|
||||
|
|
32
server.c
32
server.c
|
@ -605,6 +605,31 @@ apply_block_return(struct client *c)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct proxy *
|
||||
matched_proxy(struct client *c)
|
||||
{
|
||||
struct proxy *p;
|
||||
const char *proto;
|
||||
const char *host;
|
||||
const char *port;
|
||||
|
||||
TAILQ_FOREACH(p, &c->host->proxies, proxies) {
|
||||
if ((proto = p->match_proto) == NULL)
|
||||
proto = "gemini";
|
||||
if ((host = p->match_host) == NULL)
|
||||
host = "*";
|
||||
if ((port = p->match_port) == NULL)
|
||||
port = "*";
|
||||
|
||||
if (matches(proto, c->iri.schema) &&
|
||||
matches(host, c->domain) &&
|
||||
matches(port, c->iri.port))
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 1 if matching a proxy relay-to (and apply it), 0 otherwise */
|
||||
static int
|
||||
apply_reverse_proxy(struct client *c)
|
||||
|
@ -612,18 +637,17 @@ apply_reverse_proxy(struct client *c)
|
|||
struct proxy *p;
|
||||
struct connreq r;
|
||||
|
||||
p = &c->host->proxy;
|
||||
if (p->host == NULL)
|
||||
if ((p = matched_proxy(c)) == NULL)
|
||||
return 0;
|
||||
|
||||
c->proxy = p;
|
||||
|
||||
log_debug(c, "opening proxy connection for %s:%s",
|
||||
p->host, p->port);
|
||||
|
||||
strlcpy(r.host, p->host, sizeof(r.host));
|
||||
strlcpy(r.port, p->port, sizeof(r.port));
|
||||
|
||||
strlcpy(c->domain, p->host, sizeof(c->domain));
|
||||
|
||||
imsg_compose(&exibuf, IMSG_CONN_REQ, c->id, 0, -1, &r, sizeof(r));
|
||||
imsg_flush(&exibuf);
|
||||
|
||||
|
|
Loading…
Reference in New Issue