summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/relayd.conf40
-rw-r--r--usr.sbin/relayctl/relayctl.812
-rw-r--r--usr.sbin/relayd/parse.y514
-rw-r--r--usr.sbin/relayd/relay.c12
-rw-r--r--usr.sbin/relayd/relayd.812
-rw-r--r--usr.sbin/relayd/relayd.c67
-rw-r--r--usr.sbin/relayd/relayd.conf.5385
-rw-r--r--usr.sbin/relayd/relayd.h7
8 files changed, 556 insertions, 493 deletions
diff --git a/etc/relayd.conf b/etc/relayd.conf
index c70e08d4275..e43c8acda95 100644
--- a/etc/relayd.conf
+++ b/etc/relayd.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: relayd.conf,v 1.10 2007/12/07 17:17:00 reyk Exp $
+# $OpenBSD: relayd.conf,v 1.11 2007/12/08 17:07:08 reyk Exp $
#
# Macros
#
@@ -17,37 +17,26 @@ sshhost1="10.0.0.3"
#
# Each table will be mapped to a pf table.
#
-table webhosts {
- real port http
- check http "/" code 200
- host $webhost1
- host $webhost2
-}
-
-table fallback {
- real port http
- check icmp
- host 127.0.0.1
-}
+table <webhosts> { $webhost1 $webhost2 }
+table <fallback> { 127.0.0.1 }
#
# Services will be mapped to a rdr rule.
#
-service www {
- virtual host $ext_addr port http interface trunk0
+redirect www {
+ listen on $ext_addr port http interface trunk0
# tag every packet that goes thru the rdr rule with RELAYD
tag RELAYD
- table webhosts
- backup table fallback
+ forward to <webhosts> check http "/" code 200
+ forward to <fallback> check icmp
}
#
# Relay and protocol for HTTP layer 7 loadbalancing and SSL acceleration
#
-protocol httpssl {
- protocol http
+http protocol httpssl {
header append "$REMOTE_ADDR" to "X-Forwarded-For"
header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarded-By"
header change "Connection" to "close"
@@ -65,15 +54,14 @@ relay wwwssl {
protocol httpssl
# Forward to hosts in the webhosts table using a src/dst hash
- table webhosts loadbalance
+ forward to <webhosts> port http mode loadbalance \
+ check http "/" code 200
}
#
# Relay and protocol for simple TCP forwarding on layer 7
#
-protocol sshtcp {
- protocol tcp
-
+tcp protocol sshtcp {
# The TCP_NODELAY option is required for "smooth" terminal sessions
tcp nodelay
}
@@ -90,9 +78,7 @@ relay sshgw {
#
# Relay and protocol for a transparent HTTP proxy
#
-protocol httpfilter {
- protocol http
-
+http protocol httpfilter {
# Return HTTP/HTML error pages to the client
return error
@@ -115,5 +101,5 @@ relay httpproxy {
protocol httpfilter
# Forward to the original target host
- nat lookup
+ forward to nat lookup
}
diff --git a/usr.sbin/relayctl/relayctl.8 b/usr.sbin/relayctl/relayctl.8
index d9775aebed0..af1cb4af72f 100644
--- a/usr.sbin/relayctl/relayctl.8
+++ b/usr.sbin/relayctl/relayctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayctl.8,v 1.16 2007/12/07 17:28:05 reyk Exp $
+.\" $OpenBSD: relayctl.8,v 1.17 2007/12/08 17:07:09 reyk Exp $
.\"
.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 7 2007 $
+.Dd $Mdocdate: December 8 2007 $
.Dt RELAYCTL 8
.Os
.Sh NAME
@@ -90,5 +90,11 @@ Unix-domain socket used for communication with
.Sh HISTORY
The
.Nm
-program first appeared in
+program, formerly known as
+.Ic hoststatectl ,
+first appeared in
.Ox 4.1 .
+It was renamed to
+.Nm
+in
+.Ox 4.3 .
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index f729fb4d1eb..1865e787e99 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.97 2007/12/07 17:17:00 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.98 2007/12/08 17:07:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -94,6 +94,7 @@ static struct relay *rlay = NULL;
static struct protocol *proto = NULL;
static struct protonode node;
static u_int16_t label = 0;
+static in_port_t tableport = 0;
struct address *host_v4(const char *);
struct address *host_v6(const char *);
@@ -102,7 +103,7 @@ int host_dns(const char *, struct addresslist *,
int host(const char *, struct addresslist *,
int, in_port_t, const char *);
-struct table *table_inherit(const char *, in_port_t);
+struct table *table_inherit(struct table *);
typedef struct {
union {
@@ -110,6 +111,7 @@ typedef struct {
char *string;
struct host *host;
struct timeval tv;
+ struct table *table;
struct {
enum digest_type type;
char *digest;
@@ -120,23 +122,23 @@ typedef struct {
%}
-%token SERVICE TABLE BACKUP HOST REAL INCLUDE
-%token CHECK TCP ICMP EXTERNAL REQUEST RESPONSE
-%token TIMEOUT CODE DIGEST PORT TAG INTERFACE STYLE RETURN LABEL
-%token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT WITH
-%token SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE
-%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED URL
-%token PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER
-%token LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER QUERYSTR RETRY IP
-%token ERROR
+%token ALL APPEND BACKLOG BACKUP BUFFER CACHE CHANGE CHECK CIPHERS
+%token CODE COOKIE DEMOTE DIGEST DISABLE EXPECT EXTERNAL FILTER FORWARD
+%token FROM HASH HEADER HOST ICMP INCLUDE INTERFACE INTERVAL IP LABEL
+%token LISTEN LOADBALANCE LOG LOOKUP MARK MARKED MODE NAT NO NODELAY NOTHING
+%token ON PATH PORT PREFORK PROTO QUERYSTR REAL REDIRECT RELAY REMOVE
+%token REQUEST RESPONSE RETRY RETURN ROUNDROBIN SACK SCRIPT SEND SESSION
+%token SOCKET SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO UPDATES URL
+%token VIRTUAL WITH ERROR
%token <v.string> STRING
%token <v.number> NUMBER
-%type <v.string> interface hostname
-%type <v.number> port http_type loglevel sslcache optssl dstport mark
-%type <v.number> proto_type dstmode docheck retry log flag direction
+%type <v.string> interface hostname table
+%type <v.number> port http_type loglevel sslcache optssl mark
+%type <v.number> proto_type dstmode retry log flag direction
%type <v.host> host
%type <v.tv> timeout
%type <v.digest> digest
+%type <v.table> tablespec
%%
@@ -146,7 +148,7 @@ grammar : /* empty */
| grammar varset '\n'
| grammar main '\n'
| grammar service '\n'
- | grammar table '\n'
+ | grammar tabledef '\n'
| grammar relay '\n'
| grammar proto '\n'
| grammar error '\n' { file->errors++; }
@@ -308,14 +310,14 @@ loglevel : UPDATES { $$ = RELAYD_OPT_LOGUPDATE; }
| ALL { $$ = RELAYD_OPT_LOGALL; }
;
-service : SERVICE STRING {
+service : REDIRECT STRING {
struct service *srv;
TAILQ_FOREACH(srv, conf->services, entry)
if (!strcmp(srv->conf.name, $2))
break;
if (srv != NULL) {
- yyerror("service %s defined twice", $2);
+ yyerror("redirection %s defined twice", $2);
free($2);
YYERROR;
}
@@ -325,24 +327,24 @@ service : SERVICE STRING {
if (strlcpy(srv->conf.name, $2,
sizeof(srv->conf.name)) >=
sizeof(srv->conf.name)) {
- yyerror("service name truncated");
+ yyerror("redirection name truncated");
YYERROR;
}
free($2);
srv->conf.id = last_service_id++;
if (last_service_id == INT_MAX) {
- yyerror("too many services defined");
+ yyerror("too many redirections defined");
YYERROR;
}
service = srv;
} '{' optnl serviceopts_l '}' {
if (service->table == NULL) {
- yyerror("service %s has no table",
+ yyerror("redirection %s has no table",
service->conf.name);
YYERROR;
}
if (TAILQ_EMPTY(&service->virts)) {
- yyerror("service %s has no virtual ip",
+ yyerror("redirection %s has no virtual ip",
service->conf.name);
YYERROR;
}
@@ -353,15 +355,16 @@ service : SERVICE STRING {
service->backup = &conf->empty_table;
} else if (service->backup->conf.port !=
service->table->conf.port) {
- yyerror("service %s uses two different ports "
- "for its table and backup table",
+ yyerror("redirection %s uses two different "
+ "ports for its table and backup table",
service->conf.name);
YYERROR;
}
-
if (!(service->conf.flags & F_DISABLE))
service->conf.flags |= F_ADD;
TAILQ_INSERT_HEAD(conf->services, service, entry);
+ tableport = 0;
+ service = NULL;
}
;
@@ -369,49 +372,28 @@ serviceopts_l : serviceopts_l serviceoptsl nl
| serviceoptsl optnl
;
-serviceoptsl : TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
- port = $3;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($2, port)) == NULL) {
- free($2);
+serviceoptsl : FORWARD TO tablespec {
+ if ($3->conf.check == CHECK_NOCHECK) {
+ yyerror("table %s has no check", $3->conf.name);
+ purge_table(conf->tables, $3);
YYERROR;
}
- free($2);
-
- service->table = tb;
- service->conf.table_id = tb->conf.id;
- service->table->conf.serviceid = service->conf.id;
- service->table->conf.flags |= F_USED;
- }
- | BACKUP TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
if (service->backup) {
- yyerror("backup already specified");
- free($3);
+ yyerror("only one backup table is allowed");
+ purge_table(conf->tables, $3);
YYERROR;
}
-
- port = $4;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($3, port)) == NULL) {
- free($3);
- YYERROR;
+ if (service->table) {
+ service->backup = $3;
+ service->conf.backup_id = $3->conf.id;
+ } else {
+ service->table = $3;
+ service->conf.table_id = $3->conf.id;
}
- free($3);
-
- service->backup = tb;
- service->conf.backup_id = tb->conf.id;
- service->backup->conf.serviceid = service->conf.id;
- service->backup->conf.flags |= (F_USED|F_BACKUP);
+ $3->conf.serviceid = service->conf.id;
+ $3->conf.flags |= F_USED;
}
- | VIRTUAL HOST STRING port interface {
+ | LISTEN ON STRING port interface {
if (host($3, &service->virts,
SRV_MAX_VIRTS, $4, $5) <= 0) {
yyerror("invalid virtual ip: %s", $3);
@@ -423,6 +405,7 @@ serviceoptsl : TABLE STRING dstport {
free($5);
if (service->conf.port == 0)
service->conf.port = $4;
+ tableport = service->conf.port;
}
| DISABLE { service->conf.flags |= F_DISABLE; }
| STICKYADDR { service->conf.flags |= F_STICKY; }
@@ -430,7 +413,7 @@ serviceoptsl : TABLE STRING dstport {
if (strlcpy(service->conf.tag, $2,
sizeof(service->conf.tag)) >=
sizeof(service->conf.tag)) {
- yyerror("service tag name truncated");
+ yyerror("redirection tag name truncated");
free($2);
YYERROR;
}
@@ -439,7 +422,17 @@ serviceoptsl : TABLE STRING dstport {
| include
;
-table : TABLE STRING {
+table : '<' STRING '>' {
+ if (strlen($2) >= TABLE_NAME_SIZE) {
+ yyerror("invalid table name");
+ free($2);
+ YYERROR;
+ }
+ $$ = $2;
+ }
+ ;
+
+tabledef : TABLE table {
struct table *tb;
TAILQ_FOREACH(tb, conf->tables, entry)
@@ -454,11 +447,9 @@ table : TABLE STRING {
if ((tb = calloc(1, sizeof (*tb))) == NULL)
fatal("out of memory");
- if (strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)) >=
- sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- YYERROR;
- }
+ (void)strlcpy(tb->conf.name, $2, sizeof(tb->conf.name));
+ free($2);
+
tb->conf.id = last_table_id++;
bcopy(&conf->timeout, &tb->conf.timeout,
sizeof(struct timeval));
@@ -466,148 +457,183 @@ table : TABLE STRING {
yyerror("too many tables defined");
YYERROR;
}
- free($2);
table = tb;
- } '{' optnl tableopts_l '}' {
+ } tabledefopts_l {
if (TAILQ_EMPTY(&table->hosts)) {
yyerror("table %s has no hosts",
table->conf.name);
YYERROR;
}
- if (table->conf.check == CHECK_NOCHECK) {
- yyerror("table %s has no check",
- table->conf.name);
- YYERROR;
- }
conf->tablecount++;
TAILQ_INSERT_HEAD(conf->tables, table, entry);
}
;
-tableopts_l : tableopts_l tableoptsl nl
- | tableoptsl optnl
+tabledefopts_l : tabledefopts_l tabledefopts
+ | tabledefopts
+ ;
+
+tabledefopts : DISABLE { table->conf.flags |= F_DISABLE; }
+ | '{' optnl tablelist_l '}'
+ ;
+
+tablelist_l : tablelist comma tablelist_l
+ | tablelist optnl
;
-tableoptsl : host {
+tablelist : host {
$1->conf.tableid = table->conf.id;
$1->tablename = table->conf.name;
TAILQ_INSERT_HEAD(&table->hosts, $1, entry);
}
+ | include
+ ;
+
+tablespec : table {
+ struct table *tb;
+ if ((tb = calloc(1, sizeof (*tb))) == NULL)
+ fatal("out of memory");
+ (void)strlcpy(tb->conf.name, $1, sizeof(tb->conf.name));
+ free($1);
+ table = tb;
+ } tableopts_l {
+ struct table *tb;
+ if (table->conf.port == 0)
+ table->conf.port = tableport;
+ if ((tb = table_inherit(table)) == NULL)
+ YYERROR;
+ $$ = tb;
+ }
+ ;
+
+tableopts_l : tableopts tableopts_l
+ | tableopts
+ ;
+
+tableopts : CHECK tablecheck
+ | port { table->conf.port = $1; }
| TIMEOUT timeout {
bcopy(&$2, &table->conf.timeout,
sizeof(struct timeval));
}
- | CHECK ICMP {
- table->conf.check = CHECK_ICMP;
+ | DEMOTE STRING {
+ table->conf.flags |= F_DEMOTE;
+ if (strlcpy(table->conf.demote_group, $2,
+ sizeof(table->conf.demote_group))
+ >= sizeof(table->conf.demote_group)) {
+ yyerror("yyparse: demote group name too long");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ if (carp_demote_init(table->conf.demote_group, 1)
+ == -1) {
+ yyerror("yyparse: error initializing group "
+ "'%s'", table->conf.demote_group);
+ YYERROR;
+ }
+ }
+ | INTERVAL NUMBER {
+ if ($2 < conf->interval.tv_sec ||
+ $2 % conf->interval.tv_sec) {
+ yyerror("table interval must be "
+ "divisible by global interval");
+ YYERROR;
+ }
+ table->conf.skip_cnt = ($2 / conf->interval.tv_sec) - 1;
}
- | CHECK TCP {
- table->conf.check = CHECK_TCP;
+ | MODE dstmode {
+ switch ($2) {
+ case RELAY_DSTMODE_LOADBALANCE:
+ case RELAY_DSTMODE_HASH:
+ if (service != NULL) {
+ yyerror("mode not supported "
+ "for redirections");
+ YYERROR;
+ }
+ /* FALLTHROUGH */
+ case RELAY_DSTMODE_ROUNDROBIN:
+ if (rlay != NULL)
+ rlay->conf.dstmode = $2;
+ break;
+ }
}
- | CHECK SSL {
+ ;
+
+tablecheck : ICMP { table->conf.check = CHECK_ICMP; }
+ | TCP { table->conf.check = CHECK_TCP; }
+ | SSL {
table->conf.check = CHECK_TCP;
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
- | CHECK http_type STRING hostname CODE NUMBER {
- if ($2) {
+ | http_type STRING hostname CODE NUMBER {
+ if ($1) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
table->conf.check = CHECK_HTTP_CODE;
- if ((table->conf.retcode = $6) <= 0) {
- yyerror("invalid HTTP code: %d", $6);
+ if ((table->conf.retcode = $5) <= 0) {
+ yyerror("invalid HTTP code: %d", $5);
+ free($2);
free($3);
- free($4);
YYERROR;
}
if (asprintf(&table->sendbuf,
- "HEAD %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
+ "HEAD %s HTTP/1.0\r\n%s\r\n", $2, $3) == -1)
fatal("asprintf");
+ free($2);
free($3);
- free($4);
if (table->sendbuf == NULL)
fatal("out of memory");
table->sendbuf_len = strlen(table->sendbuf);
}
- | CHECK http_type STRING hostname digest {
- if ($2) {
+ | http_type STRING hostname digest {
+ if ($1) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
table->conf.check = CHECK_HTTP_DIGEST;
if (asprintf(&table->sendbuf,
- "GET %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
+ "GET %s HTTP/1.0\r\n%s\r\n", $2, $3) == -1)
fatal("asprintf");
+ free($2);
free($3);
- free($4);
if (table->sendbuf == NULL)
fatal("out of memory");
table->sendbuf_len = strlen(table->sendbuf);
- (void)strlcpy(table->conf.digest, $5.digest,
+ (void)strlcpy(table->conf.digest, $4.digest,
sizeof(table->conf.digest));
- table->conf.digest_type = $5.type;
- free($5.digest);
+ table->conf.digest_type = $4.type;
+ free($4.digest);
}
- | CHECK SEND sendbuf EXPECT STRING optssl {
+ | SEND sendbuf EXPECT STRING optssl {
table->conf.check = CHECK_SEND_EXPECT;
- if ($6) {
+ if ($5) {
conf->flags |= F_SSL;
table->conf.flags |= F_SSL;
}
- if (strlcpy(table->conf.exbuf, $5,
+ if (strlcpy(table->conf.exbuf, $4,
sizeof(table->conf.exbuf))
>= sizeof(table->conf.exbuf)) {
yyerror("yyparse: expect buffer truncated");
- free($5);
+ free($4);
YYERROR;
}
translate_string(table->conf.exbuf);
- free($5);
+ free($4);
}
- | CHECK SCRIPT STRING {
+ | SCRIPT STRING {
table->conf.check = CHECK_SCRIPT;
- if (strlcpy(table->conf.path, $3,
+ if (strlcpy(table->conf.path, $2,
sizeof(table->conf.path)) >=
sizeof(table->conf.path)) {
yyerror("script path truncated");
- free($3);
- YYERROR;
- }
- free($3);
- }
- | REAL port {
- table->conf.port = $2;
- }
- | DEMOTE STRING {
- table->conf.flags |= F_DEMOTE;
- if (strlcpy(table->conf.demote_group, $2,
- sizeof(table->conf.demote_group))
- >= sizeof(table->conf.demote_group)) {
- yyerror("yyparse: demote group name too long");
free($2);
YYERROR;
}
free($2);
- if (carp_demote_init(table->conf.demote_group, 1)
- == -1) {
- yyerror("yyparse: error initializing group "
- "'%s'", table->conf.demote_group);
- YYERROR;
- }
- }
- | DISABLE {
- table->conf.flags |= F_DISABLE;
- }
- | INTERVAL NUMBER {
- if ($2 < conf->interval.tv_sec ||
- $2 % conf->interval.tv_sec) {
- yyerror("table interval must be "
- "divisible by global interval");
- YYERROR;
- }
- table->conf.skip_cnt = ($2 / conf->interval.tv_sec) - 1;
}
- | include
;
digest : DIGEST STRING
@@ -628,31 +654,32 @@ digest : DIGEST STRING
}
;
-proto : PROTO STRING {
+proto : proto_type PROTO STRING {
struct protocol *p;
- if (strcmp($2, "default") == 0) {
+ if (strcmp($3, "default") == 0) {
p = &conf->proto_default;
} else {
TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
+ if (!strcmp(p->name, $3))
break;
}
if (p != NULL) {
- yyerror("protocol %s defined twice", $2);
- free($2);
+ yyerror("protocol %s defined twice", $3);
+ free($3);
YYERROR;
}
if ((p = calloc(1, sizeof (*p))) == NULL)
fatal("out of memory");
- if (strlcpy(p->name, $2, sizeof(p->name)) >=
+ if (strlcpy(p->name, $3, sizeof(p->name)) >=
sizeof(p->name)) {
yyerror("protocol name truncated");
YYERROR;
}
- free($2);
+ free($3);
p->id = last_proto_id++;
+ p->type = $1;
p->cache = RELAY_CACHESIZE;
p->type = RELAY_PROTO_TCP;
p->tcpflags = TCPFLAG_DEFAULT;
@@ -667,7 +694,7 @@ proto : PROTO STRING {
RB_INIT(&p->request_tree);
RB_INIT(&p->response_tree);
proto = p;
- } '{' optnl protopts_l '}' {
+ } protopts_n {
conf->protocount++;
if ((proto->sslflags & SSLFLAG_VERSION) == 0) {
@@ -679,6 +706,11 @@ proto : PROTO STRING {
}
;
+protopts_n : /* empty */
+ | '{' '}'
+ | '{' optnl protopts_l '}'
+ ;
+
protopts_l : protopts_l protoptsl nl
| protoptsl optnl
;
@@ -687,7 +719,6 @@ protoptsl : SSL sslflags
| SSL '{' sslflags_l '}'
| TCP tcpflags
| TCP '{' tcpflags_l '}'
- | PROTO proto_type { proto->type = $2; }
| RETURN ERROR opteflags { proto->flags |= F_RETURN; }
| RETURN ERROR '{' eflags_l '}' { proto->flags |= F_RETURN; }
| LABEL STRING {
@@ -1111,6 +1142,8 @@ relay : RELAY STRING {
conf->relaycount++;
SPLAY_INIT(&rlay->sessions);
TAILQ_INSERT_HEAD(conf->relays, rlay, entry);
+ tableport = 0;
+ rlay = NULL;
}
;
@@ -1142,103 +1175,75 @@ relayoptsl : LISTEN ON STRING port optssl {
rlay->conf.flags |= F_SSL;
conf->flags |= F_SSL;
}
+ tableport = h->port;
}
- | FORWARD TO STRING port retry {
- struct addresslist al;
- struct address *h;
+ | FORWARD TO forwardspec
+ | FORWARD TIMEOUT NUMBER {
+ if ((rlay->conf.timeout.tv_sec = $3) < 0) {
+ yyerror("invalid timeout: %d", $3);
+ YYERROR;
+ }
+ }
+ | PROTO STRING {
+ struct protocol *p;
- if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
- "specified", rlay->conf.name);
- free($3);
+ TAILQ_FOREACH(p, conf->protos, entry)
+ if (!strcmp(p->name, $2))
+ break;
+ if (p == NULL) {
+ yyerror("no such protocol: %s", $2);
+ free($2);
YYERROR;
}
+ p->flags |= F_USED;
+ rlay->conf.proto = p->id;
+ rlay->proto = p;
+ free($2);
+ }
+ | DISABLE { rlay->conf.flags |= F_DISABLE; }
+ | include
+ ;
- TAILQ_INIT(&al);
- if (host($3, &al, 1, $4, NULL) <= 0) {
- yyerror("invalid listen ip: %s", $3);
- free($3);
+forwardspec : tablespec {
+ if (rlay->dsttable) {
+ yyerror("table already specified");
+ purge_table(conf->tables, $1);
YYERROR;
}
- free($3);
- h = TAILQ_FIRST(&al);
- bcopy(&h->ss, &rlay->conf.dstss,
- sizeof(rlay->conf.dstss));
- rlay->conf.dstport = h->port;
- rlay->conf.dstretry = $5;
+
+ rlay->dsttable = $1;
+ rlay->dsttable->conf.flags |= F_USED;
+ rlay->conf.dsttable = $1->conf.id;
+ rlay->conf.dstport = $1->conf.port;
}
- | SERVICE STRING retry {
- struct service *svc;
- struct address *h;
+ | STRING port retry {
+ struct addresslist al;
+ struct address *h;
if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
+ yyerror("relay %s target or redirection already "
"specified", rlay->conf.name);
- free($2);
+ free($1);
YYERROR;
}
- if ((svc = service_findbyname(conf, $2)) == NULL) {
- yyerror("relay %s for unknown service %s",
- rlay->conf.name, $2);
- free($2);
+ TAILQ_INIT(&al);
+ if (host($1, &al, 1, $2, NULL) <= 0) {
+ yyerror("invalid listen ip: %s", $1);
+ free($1);
YYERROR;
}
- free($2);
- h = TAILQ_FIRST(&svc->virts);
+ free($1);
+ h = TAILQ_FIRST(&al);
bcopy(&h->ss, &rlay->conf.dstss,
sizeof(rlay->conf.dstss));
rlay->conf.dstport = h->port;
rlay->conf.dstretry = $3;
}
- | TABLE STRING dstport dstmode docheck {
- struct table *tb;
-
- rlay->conf.dstport = $3;
- if (rlay->conf.dstport == 0)
- rlay->conf.dstport = rlay->conf.port;
-
- if ((tb = table_inherit($2, rlay->conf.dstport)) ==
- NULL) {
- free($2);
- YYERROR;
- }
- free($2);
- rlay->conf.dsttable = tb->conf.id;
- rlay->dsttable = tb;
- rlay->conf.dstport = tb->conf.port;
- rlay->conf.dstmode = $4;
- rlay->conf.dstcheck = $5;
- rlay->dsttable->conf.flags |= F_USED;
- }
- | PROTO STRING {
- struct protocol *p;
-
- TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
- break;
- if (p == NULL) {
- yyerror("no such protocol: %s", $2);
- free($2);
- YYERROR;
- }
- p->flags |= F_USED;
- rlay->conf.proto = p->id;
- rlay->proto = p;
- free($2);
- }
- | NAT LOOKUP retry {
+ | NAT LOOKUP retry {
rlay->conf.flags |= F_NATLOOK;
rlay->conf.dstretry = $3;
}
- | TIMEOUT NUMBER {
- if ((rlay->conf.timeout.tv_sec = $2) < 0) {
- yyerror("invalid timeout: %d", $2);
- YYERROR;
- }
- }
- | DISABLE { rlay->conf.flags |= F_DISABLE; }
- | include
;
dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
@@ -1247,19 +1252,11 @@ dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
| HASH { $$ = RELAY_DSTMODE_HASH; }
;
-docheck : /* empty */ { $$ = 1; }
- | NO CHECK { $$ = 0; }
- ;
-
interface : /*empty*/ { $$ = NULL; }
| INTERFACE STRING { $$ = $2; }
;
-dstport : /* empty */ { $$ = 0; }
- | port { $$ = $1; }
- ;
-
-host : HOST STRING retry {
+host : STRING retry {
struct address *a;
struct addresslist al;
@@ -1267,9 +1264,9 @@ host : HOST STRING retry {
fatal("out of memory");
TAILQ_INIT(&al);
- if (host($2, &al, 1, 0, NULL) <= 0) {
+ if (host($1, &al, 1, 0, NULL) <= 0) {
yyerror("invalid host %s", $2);
- free($2);
+ free($1);
free($$);
YYERROR;
}
@@ -1277,16 +1274,16 @@ host : HOST STRING retry {
memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss));
free(a);
- if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >=
+ if (strlcpy($$->conf.name, $1, sizeof($$->conf.name)) >=
sizeof($$->conf.name)) {
yyerror("host name truncated");
- free($2);
+ free($1);
free($$);
YYERROR;
}
- free($2);
+ free($1);
$$->conf.id = last_host_id++;
- $$->conf.retry = $3;
+ $$->conf.retry = $2;
if (last_host_id == INT_MAX) {
yyerror("too many hosts defined");
free($$);
@@ -1320,6 +1317,7 @@ log : /* empty */ { $$ = 0; }
;
comma : ','
+ | nl
| /* empty */
;
@@ -1397,6 +1395,7 @@ lookup(char *s)
{ "lookup", LOOKUP },
{ "mark", MARK },
{ "marked", MARKED },
+ { "mode", MODE },
{ "nat", NAT },
{ "no", NO },
{ "nodelay", NODELAY },
@@ -1408,6 +1407,7 @@ lookup(char *s)
{ "protocol", PROTO },
{ "query", QUERYSTR },
{ "real", REAL },
+ { "redirect", REDIRECT },
{ "relay", RELAY },
{ "remove", REMOVE },
{ "request", REQUEST },
@@ -1418,7 +1418,6 @@ lookup(char *s)
{ "sack", SACK },
{ "script", SCRIPT },
{ "send", SEND },
- { "service", SERVICE },
{ "session", SESSION },
{ "socket", SOCKET },
{ "ssl", SSL },
@@ -1654,7 +1653,7 @@ nodigits:
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && \
+ x != '{' && x != '}' && x != '<' && x != '>' && \
x != '!' && x != '=' && x != '#' && \
x != ','))
@@ -1827,7 +1826,7 @@ parse_config(const char *filename, int opts)
}
if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) {
- log_warnx("no services, nothing to do");
+ log_warnx("no redirections, nothing to do");
errors++;
}
@@ -2086,53 +2085,45 @@ host(const char *s, struct addresslist *al, int max,
}
struct table *
-table_inherit(const char *name, in_port_t port)
+table_inherit(struct table *tb)
{
char pname[TABLE_NAME_SIZE + 6];
struct host *h, *dsth;
- struct table *dsttb, *tb;
+ struct table *dsttb, *oldtb;
/* Get the table or table template */
- if ((dsttb = table_findbyname(conf, name)) == NULL) {
- yyerror("unknown table or template %s", name);
+ if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
+ yyerror("unknown table %s", tb->conf.name);
+ purge_table(NULL, tb);
return (NULL);
}
if (dsttb->conf.port != 0)
- return (dsttb);
+ fatal("invalid table"); /* should not happen */
- if (port == 0) {
+ if (tb->conf.port == 0) {
yyerror("invalid port");
+ purge_table(NULL, tb);
return (NULL);
}
/* Check if a matching table already exists */
- snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port));
- if ((tb = table_findbyname(conf, pname)) != NULL) {
- if (tb->conf.port == 0) {
- yyerror("invalid table");
- return (NULL);
- }
- return (tb);
+ if (snprintf(pname, sizeof(pname), "%s:%u",
+ tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
+ yyerror("invalid table name");
+ return (NULL);
}
+ (void)strlcpy(tb->conf.name, pname, sizeof(tb->conf.name));
+ if ((oldtb = table_findbyconf(conf, tb)) != NULL)
+ return (oldtb);
/* Create a new table */
- if ((tb = calloc(1, sizeof (*tb))) == NULL)
- fatal("out of memory");
- bcopy(dsttb, tb, sizeof(*tb));
- if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name))
- >= sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- return (NULL);
- }
- if (dsttb->sendbuf != NULL &&
- (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL)
- fatal("out of memory");
- tb->conf.port = port;
tb->conf.id = last_table_id++;
if (last_table_id == INT_MAX) {
yyerror("too many tables defined");
+ purge_table(NULL, tb);
return (NULL);
}
+ tb->conf.flags |= dsttb->conf.flags;
/* Copy the associated hosts */
bzero(&tb->hosts, sizeof(tb->hosts));
@@ -2144,6 +2135,7 @@ table_inherit(const char *name, in_port_t port)
h->conf.id = last_host_id++;
if (last_host_id == INT_MAX) {
yyerror("too many hosts defined");
+ purge_table(NULL, tb);
return (NULL);
}
h->conf.tableid = tb->conf.id;
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index 98a74dcbd90..8a3230dc3f4 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.75 2007/12/07 17:17:01 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.76 2007/12/08 17:07:09 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -494,7 +494,7 @@ relay_init(void)
}
log_info("adding %d hosts from table %s%s",
rlay->dstnhosts, rlay->dsttable->conf.name,
- rlay->conf.dstcheck ? "" : " (no check)");
+ rlay->dsttable->conf.check ? "" : " (no check)");
}
}
@@ -2020,7 +2020,7 @@ relay_from_table(struct session *con)
u_int32_t p = con->outkey;
int idx = 0;
- if (rlay->conf.dstcheck && !table->up) {
+ if (table->conf.check && !table->up) {
log_debug("relay_from_table: no active hosts");
return (-1);
}
@@ -2045,13 +2045,13 @@ relay_from_table(struct session *con)
host->conf.name, p, idx);
while (host != NULL) {
DPRINTF("relay_from_table: host %s", host->conf.name);
- if (!rlay->conf.dstcheck || host->up == HOST_UP)
+ if (!table->conf.check || host->up == HOST_UP)
goto found;
host = TAILQ_NEXT(host, entry);
}
- TAILQ_FOREACH(host, &rlay->dsttable->hosts, entry) {
+ TAILQ_FOREACH(host, &table->hosts, entry) {
DPRINTF("relay_from_table: next host %s", host->conf.name);
- if (!rlay->conf.dstcheck || host->up == HOST_UP)
+ if (!table->conf.check || host->up == HOST_UP)
goto found;
}
diff --git a/usr.sbin/relayd/relayd.8 b/usr.sbin/relayd/relayd.8
index 0c446379a98..bd9defa4b3d 100644
--- a/usr.sbin/relayd/relayd.8
+++ b/usr.sbin/relayd/relayd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayd.8,v 1.11 2007/12/07 17:19:42 deraadt Exp $
+.\" $OpenBSD: relayd.8,v 1.12 2007/12/08 17:07:09 reyk Exp $
.\"
.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 7 2007 $
+.Dd $Mdocdate: December 8 2007 $
.Dt RELAYD 8
.Os
.Sh NAME
@@ -134,8 +134,14 @@ Unix-domain socket used for communication with
.Sh HISTORY
The
.Nm
-program first appeared in
+program, formerly known as
+.Ic hoststated ,
+first appeared in
.Ox 4.1 .
+It was renamed to
+.Nm
+in
+.Ox 4.3 .
.Sh AUTHORS
.An -nosplit
The
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index 938cf767a97..b2c5937e445 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.62 2007/12/07 17:17:01 reyk Exp $ */
+/* $OpenBSD: relayd.c,v 1.63 2007/12/08 17:07:09 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -441,7 +441,6 @@ void
purge_config(struct relayd *env, u_int8_t what)
{
struct table *table;
- struct host *host;
struct service *service;
struct address *virt;
struct protocol *proto;
@@ -449,21 +448,8 @@ purge_config(struct relayd *env, u_int8_t what)
struct session *sess;
if (what & PURGE_TABLES && env->tables != NULL) {
- while ((table = TAILQ_FIRST(env->tables)) != NULL) {
-
- while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
- TAILQ_REMOVE(&table->hosts, host, entry);
- free(host);
- }
- if (table->sendbuf != NULL)
- free(table->sendbuf);
- if (table->conf.flags & F_SSL)
- SSL_CTX_free(table->ssl_ctx);
-
- TAILQ_REMOVE(env->tables, table, entry);
-
- free(table);
- }
+ while ((table = TAILQ_FIRST(env->tables)) != NULL)
+ purge_table(env->tables, table);
free(env->tables);
env->tables = NULL;
}
@@ -541,6 +527,25 @@ purge_tree(struct proto_tree *tree)
}
void
+purge_table(struct tablelist *head, struct table *table)
+{
+ struct host *host;
+
+ while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
+ TAILQ_REMOVE(&table->hosts, host, entry);
+ free(host);
+ }
+ if (table->sendbuf != NULL)
+ free(table->sendbuf);
+ if (table->conf.flags & F_SSL)
+ SSL_CTX_free(table->ssl_ctx);
+
+ if (head != NULL)
+ TAILQ_REMOVE(head, table, entry);
+ free(table);
+}
+
+void
imsg_event_add(struct imsgbuf *ibuf)
{
ibuf->events = EV_READ;
@@ -798,6 +803,34 @@ table_findbyname(struct relayd *env, const char *name)
return (NULL);
}
+struct table *
+table_findbyconf(struct relayd *env, struct table *tb)
+{
+ struct table *table;
+ struct table_config a, b;
+
+ bcopy(&tb->conf, &a, sizeof(a));
+ a.id = a.serviceid = 0;
+ a.flags &= ~(F_USED|F_BACKUP);
+
+ TAILQ_FOREACH(table, env->tables, entry) {
+ bcopy(&table->conf, &b, sizeof(b));
+ b.id = b.serviceid = 0;
+ b.flags &= ~(F_USED|F_BACKUP);
+
+ /*
+ * Compare two tables and return the existing table if
+ * the configuration seems to be the same.
+ */
+ if (bcmp(&a, &b, sizeof(b)) == 0 &&
+ ((tb->sendbuf == NULL && table->sendbuf == NULL) ||
+ (tb->sendbuf != NULL && table->sendbuf != NULL &&
+ strcmp(tb->sendbuf, table->sendbuf) == 0)))
+ return (table);
+ }
+ return (NULL);
+}
+
struct service *
service_findbyname(struct relayd *env, const char *name)
{
diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5
index 56e0e71ba27..b68a36412da 100644
--- a/usr.sbin/relayd/relayd.conf.5
+++ b/usr.sbin/relayd/relayd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayd.conf.5,v 1.71 2007/12/07 17:28:05 reyk Exp $
+.\" $OpenBSD: relayd.conf.5,v 1.72 2007/12/08 17:07:09 reyk Exp $
.\"
.\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 7 2007 $
+.Dd $Mdocdate: December 8 2007 $
.Dt RELAYD.CONF 5
.Os
.Sh NAME
@@ -36,17 +36,19 @@ configuration file.
Global settings for
.Xr relayd 8 .
.It Sy Tables
-Table definitions describe the content of a
+Table definitions describe a list of hosts like
.Xr pf 4
-table and the method used for checking the health of the hosts
-they contain.
-.It Sy Services
-Services will be translated to
+tables.
+They are used for relay and redirection target selection with the
+described options and health checking on the host they contain.
+.It Sy Redirections
+Redirections will be translated to
.Xr pf 4
-rdr rules if their table or backup table have content.
+rdr rules for stateful forwarding to a target host from a
+health-checked table on layer 3.
.It Sy Relays
-Relays allow layer 7 load balancing, SSL acceleration, and
-general purpose TCP proxying.
+Relays allow application layer load balancing, SSL acceleration, and
+general purpose TCP proxying on layer 7.
.It Sy Protocols
Protocols are predefined protocol handlers and settings for relays.
.El
@@ -80,7 +82,7 @@ Macro names must start with a letter, and may contain letters, digits,
and underscores.
Macro names may not be reserved words (for example,
.Ic table ,
-.Ic service ,
+.Ic relay ,
or
.Ic timeout ) .
Macros are not expanded inside quotes.
@@ -89,12 +91,9 @@ For example:
.Bd -literal -offset indent
www1="10.0.0.1"
www2="10.0.0.2"
-table webhosts {
- check tcp
- timeout 300
- real port 80
- host $www1
- host $www2
+table \*(Ltwebhosts\*(Gt {
+ $www1
+ $www2
}
.Ed
.Sh GLOBAL CONFIGURATION
@@ -156,10 +155,59 @@ The default interval is 200 milliseconds and it must not exceed the
global interval.
.El
.Sh TABLES
-Tables are used to group a set of hosts that can be checked using the same
-method.
-Only one health-checking method can be used per table.
-Table specific configuration directives are described below.
+Tables are used to group a set of hosts as the target for redirections
+or relays, they will be mapped to a
+.Xr pf 4
+table for redirections.
+Tables may be defined with the following attribute:
+.Bl -tag -width disable
+.It Ic disable
+Start the table disabled \(en no hosts will be checked in this table.
+The table can be later enabled through
+.Xr relayctl 8 .
+.Pp
+.El
+Each table must contain at least one host, multiple hosts are
+separated by newline, comma, or whitespace.
+Host entries may be defined with the following attribute:
+.Bl -tag -width retry
+.It Ic retry Ar number
+The optional retry option adds a tolerance for failed host checks,
+the check will be retried for
+.Ar number
+more times before setting the host state to down.
+If this table is used by a relay, it will also specify the number of
+retries for outgoing connection attempts.
+.El
+.Pp
+For example,
+.Bd -literal -offset indent
+table \*(Ltservice\*(Gt { 192.168.1.1, 192.168.1.2, 192.168.2.3 }
+table \*(Ltbackup\*(Gt disable { 10.1.5.1 retry 2 }
+
+redirect "www" {
+ listen on www.example.com port 80
+ forward to \*(Ltservice\*(Gt check http "/" code 200
+ forward to \*(Ltbackup\*(Gt check http "/" code 200
+}
+.Ed
+.Pp
+Tables are used by the
+.Ic forward to
+directives in redirections or relays with a set of general options,
+health-checking rules, and timings,
+see the
+.Sx REDIRECTIONS
+and
+.Sx RELAYS
+sections for more information about the forward context.
+Table specific configuration directives are described below,
+multiple options can be appended to the
+.Ic forward to
+directives, separated by whitespaces.
+.Pp
+The following options will configure the health-checking method for
+the table, it is mandatory for redirections:
.Bl -tag -width Ds
.It Xo
.Ic check http Ar path
@@ -263,6 +311,10 @@ milliseconds.
Perform a complete SSL handshake with each host to check their availability.
.It Ic check tcp
Use a simple TCP connect to check that hosts are up.
+.El
+.Pp
+The following general table options are available:
+.Bl -tag -width Ds
.It Ic demote Ar group
Enable the per-table
.Xr carp 4
@@ -274,107 +326,128 @@ see the
.Ic group
keyword in
.Xr ifconfig 8 .
-.It Ic disable
-Start the table disabled \(en no hosts will be checked in this table.
-The table can be later enabled through
-.Xr relayctl 8 .
-.It Xo
-.Ic host Ar address
-.Op Ic retry Ar number
-.Xc
-Add the host whose address is
-.Ar address
-to the list of hosts to be checked in this table.
-Each table needs at least one host.
-The optional retry option adds a tolerance for failed host checks,
-the check will be retried for
-.Ar number
-more times before setting the host state to down.
.It Ic interval Ar number
Override the global interval and specify one for this table.
It must be a multiple of the global interval.
-.It Ic real port Ar port
-When using the TCP or HTTP checking methods, use this
-.Ar port
-to connect to hosts.
-If this parameter is not specified,
-.Xr relayd 8
-will create a template table which inherits the port from the
-referencing service or relay.
-Main and backup tables need to have the same real port.
.It Ic timeout Ar number
Set the timeout in milliseconds for each host that is checked using
TCP as the transport.
This will override the global timeout, which is 200 milliseconds by default.
.El
-.Sh SERVICES
-Services represent a
+.Pp
+The following options will set the scheduling algoritm to select a
+host from the specified table:
+.Bl -tag -width Ds
+.It Ic mode roundrobin
+Distributes the outgoing connections using a round-robin scheduler
+through all active hosts.
+This is the default mode and will be used if no option has been specified,
+it is supported by redirections and relays.
+.It Ic mode loadbalance
+Balances the outgoing connections across the active hosts based on the
+hashed name of the table, the source and destination addresses,
+and the corresponding ports.
+This mode is only supported by relays.
+.It Ic mode hash
+Like the
+.Ic loadbalance
+mode, but without including the source and destination addresses and
+ports.
+Additional input can be fed into the hash by looking at HTTP
+headers and GET variables; see the
+.Sx PROTOCOLS
+section below.
+This mode is only supported by relays.
+.El
+.Sh REDIRECTIONS
+Redirections represent a
.Xr pf 4
rdr rule.
-They are used to specify which addresses will be redirected
-to the hosts in the specified tables.
-The configuration directives that are valid in this context are described
-below.
+They are used for stateful redirections to the hosts in the specified
+tables,
+.Xr pf 4
+will rewrite the target IP-addresses and ports of the incoming
+connections, operating on layer 3.
+The configuration directives that are valid in the
+.Ic redirect
+context are described below:
.Bl -tag -width Ds
-.It Ic backup table Ar name
-Specify the table to switch to when all hosts in the main table
-are seen as down or disabled.
.It Ic disable
Set the service initially disabled.
It can be later enabled through
.Xr relayctl 8 .
+.It Xo
+.Ic forward to
+.Aq Ar table
+.Op Ic port Ar number
+.Ar options...
+.Xc
+Specify the tables of target hosts to be used, see the
+.Sx TABLES
+section above for information about the table options.
+If the
+.Ic port
+option is not specified, the port from the
+.Ic listen on
+directive will be used.
+This directive can be specified twice, the second entry will be used
+as the backup table if all hosts in the main table are down.
+At least one entry for the main table is mandatory.
+.It Xo
+.Ic listen on Ar address Ic port Ar port
+.Op Ic interface Ar name
+.Xc
+Specify an
+.Ar address
+and a
+.Ar port
+to listen on.
+.Xr pf 4
+will redirect incoming connections for the specified target to the
+hosts in the main or backup table.
+The rdr rule can be optionally restricted to a given interface name.
.It Ic sticky-address
This has the same effect than specifying sticky-address
for a rdr rule in
.Xr pf.conf 5 .
It will ensure that multiple connections from the same source are
mapped to the same redirection address.
-.It Xo
-.Ic table Ar name Op Ic port Ar port
-.Xc
-Specify the main table to be used.
-Optionally supply a port which will
-override the real port specification in the table.
-This is mandatory.
.It Ic tag Ar name
Automatically tag packets passing through the
.Xr pf 4
rdr rule with the name supplied.
This allows simpler filter rules.
-.It Ic virtual host Ar address Ic port Ar port
-Specify an
-.Ar address
-and a
-.Ar port
-that will be used to redirect requests
-to the hosts in the main or backup table.
-Optionally an interface name can be given as follows,
-to specify which interface the rdr rule will be enabled on:
-.Bd -literal -offset indent
-interface ``ifname''
-.Ed
.El
.Sh RELAYS
-Relays will forward TCP traffic between a client and a target server.
-In contrast to IP forwarding and redirection in the network stack, a
-relay will accept incoming TCP connections from remote clients as a
+Relays will forward traffic between a client and a target server.
+In contrast to redirections and IP forwarding in the network stack, a
+relay will accept incoming connections from remote clients as a
server, open an outgoing connection to a target host, and forward
-any traffic between the target host and the remote client.
-A relay is also called an application layer or layer 7 proxy.
+any traffic between the target host and the remote client,
+operating on layer 7.
+A relay is also called an application layer gateway or layer 7 proxy.
.Pp
The main purpose of a relay is to provide advanced load balancing
functionality based on specified protocol characteristics, such as
HTTP headers, to provide SSL acceleration functionality and to allow
basic handling of the underlying application protocol.
.Pp
-The relay configuration directives are described below.
+The
+.Ic relay
+configuration directives are described below:
.Bl -tag -width Ds
.It Xo
-.Ic listen on Ar address Ic port Ar port
+.Ic listen on Ar address
+.Op Ic port Ar port
.Op Ic ssl
.Xc
Specify the address and port for the relay to listen on.
The relay will accept incoming connections to the specified address.
+If the
+.Ic port
+option is not specified, the port from the
+.Ic listen on
+directive will be used.
.Pp
If the
.Ic ssl
@@ -391,56 +464,34 @@ See
.Xr ssl 8
for details about SSL server certificates.
.It Xo
-.Ic forward to Ar address Ic port Ar port
+.Ic forward to
+.Ar address
+.Op Ic port Ar port
.Op Ic retry Ar number
.Xc
Specify the address and port of the target host to connect to.
-.It Xo
-.Ic service Ar name
-.Op Ic retry Ar number
-.Xc
-Use the first virtual IP address and port from the specified service
-as the target host to connect to.
-This is exclusive to the
-.Ic forward to
-and
-.Ic table
-directives.
-.It Xo
-.Ic table Ar name Ar mode
-.Op Ic no check
-.Xc
-Get the target host from the specified table.
-The following modes are available to select a host from the specified
-table:
-.Pp
-.Bl -tag -width loadbalance -offset indent -compact
-.It Ic roundrobin
-Distributes the outgoing connections using a round-robin scheduler
-through all active hosts.
-.It Ic loadbalance
-Balances the outgoing connections across the active hosts based on the
-hashed name of the table, the source and destination addresses,
-and the corresponding ports.
-.It Ic hash
-Like the
-.Ic loadbalance
-mode, but without including the source and destination addresses and
-ports.
-Additional input can be fed into the hash by looking at HTTP
-headers and GET variables; see the
-.Sx PROTOCOLS
-section below.
-.El
+If the
+.Ic port
+option is not specified, the port from the
+.Ic listen on
+directive will be used.
.Pp
The optional host retry option will be used as a tolerance for failed
host connections; the connection will be retried for
.Ar number
more times.
-See the
+.It Xo
+.Ic forward to
+.Aq Ar table
+.Op Ic port Ar port
+.Ar options...
+.Xc
+Like the previous directive, but connect to a host from the specified
+table, see the
.Sx TABLES
-section for details about host entries.
+section above for information about the table options.
.It Xo
+.Ic forward to
.Ic nat lookup
.Op Ic retry Ar number
.Xc
@@ -451,13 +502,10 @@ rule in
to a relay listening on localhost, this directive will
look up the real destination address of the intended target host,
allowing the relay to be run as a transparent proxy.
-If either the
-.Ic forward to ,
-.Ic service ,
-or
-.Ic table
-directive is present, it will be used as a backup if the NAT lookup
-failed.
+If an additional
+.Ic forward to
+directive to a specified address or table is present,
+it will be used as a backup if the NAT lookup failed.
.It Ic timeout Ar seconds
Specify the timeout in seconds for accepted sessions.
The default timeout is 600 seconds (10 minutes).
@@ -475,17 +523,13 @@ Protocols are templates defining actions and settings for relays.
They allow setting generic TCP options, SSL settings, and actions
specific to the selected application layer protocol.
.Pp
-The protocol configuration directives are described below.
+The protocol directive is available for a number of different
+application layer protocols:
.Bl -tag -width Ds
-.It Ic protocol Ar type
-Enable special handling of the specified application layer protocol.
-The supported TCP protocols are:
-.Pp
-.Bl -tag -width http -offset indent -compact
-.It Ic http
+.It Ic http protocol
Handle the Hypertext Transfer Protocol
(HTTP or "HTTPS" if encapsulated in a SSL tunnel).
-.It Ic tcp
+.It Ic tcp protocol
Generic handler for TCP-based protocols.
.El
.Pp
@@ -496,14 +540,17 @@ stateless datagram-based protocol which has to look into the
application layer protocol to find any possible state information.
The supported UDP protocols are:
.Pp
-.Bl -tag -width http -offset indent -compact
-.It Ic dns
+.Bl -tag -width Ds
+.It Ic dns protocol
Domain Name System (DNS) protocol.
The request IDs in the DNS header will be used to match the state.
.Xr relayd 8
will replace these IDs with random values to compensate for
predictable values generated by some hosts.
.El
+.Pp
+The available configuration directives are described below:
+.Bl -tag -width Ds
.It Xo
.Op Ar direction
.Op Ar type
@@ -712,8 +759,8 @@ The label will be printed as part of the error message if the
.Ic return error
option is set and may contain HTML tags, for example:
.Bd -literal -offset indent
-label "<a href='http://example.com/advisory.pl?id=7359'>\e
- Advisory provided by example.com</a>"
+label "\*(Lta href='http://example.com/advisory.pl?id=7359'\*(Gt\e
+ Advisory provided by example.com\*(Lt/a\*(Gt"
url filter digest 5c1e03f58f8ce0b457474ffb371fd1ef
url filter digest 80c1a7b8337462093ef8359c57b4d56a
no label
@@ -867,31 +914,18 @@ www4=front-www4.private.example.com
interval 5
-table phphosts {
- timeout 300
- real port 8080
- check http "/" digest "630aa3c2f..."
- host $www1
- host $www2
- host $www3
- host $www4
-}
+table \*(Ltphphosts\*(Gt { $www1, $www2, $www3, $www4 }
+table \*(Ltsorryhost\*(Gt disable { sorryhost.private.example.com }
-table sorryhost {
- check icmp
- disable
- timeout 300
- real port 8080
- host sorryhost.private.example.com
-}
+redirect "www" {
+ listen on www.example.com port 8080 interface trunk0
+ listen on www6.example.com port 80 interface trunk0
-service www {
- virtual host www.example.com port 8080 interface trunk0
- virtual host www6.example.com port 80 interface trunk0
+ tag REDIRECTED
- tag RELAYD
- table phphosts
- backup table sorryhost
+ forward to \*(Ltphphosts\*(Gt port 8080 timeout 300 \e
+ check http "/" digest "630aa3c2f..."
+ forward to \*(Ltsorryhost\*(Gt port 8080 timeout 300 check icmp
}
.Ed
.Pp
@@ -899,7 +933,7 @@ The following configuration would add a relay to forward
secure HTTPS connections to a pool of HTTP webservers
using the
.Ic loadbalance
-protocol (SSL acceleration and layer 7 load balancing).
+mode (SSL acceleration and layer 7 load balancing).
The HTTP protocol definition will add two HTTP headers containing
address information of the client and the server, set the
.Dq Keep-Alive
@@ -908,8 +942,7 @@ and include the
.Dq sessid
variable in the hash to calculate the target host:
.Bd -literal -offset indent
-protocol http_ssl {
- protocol http
+http protocol "http_ssl" {
header append "$REMOTE_ADDR" to "X-Forwarded-For"
header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarded-By"
header change "Keep-Alive" to "$TIMEOUT"
@@ -920,10 +953,10 @@ protocol http_ssl {
ssl { sslv2, ciphers "MEDIUM:HIGH" }
}
-relay sslaccel {
- listen on www.example.com port 443 ssl
- protocol http_ssl
- table phphosts loadbalance
+relay "sslaccel" {
+ listen on www.example.com port 443 ssl
+ protocol "http_ssl"
+ forward to \*(Ltphphosts\*(Gt port 8080 mode loadbalance check tcp
}
.Ed
.Pp
@@ -936,13 +969,13 @@ option will allow a
SSH session without delays between keystrokes or displayed output on
the terminal:
.Bd -literal -offset indent
-protocol myssh {
+tcp protocol "myssh" {
tcp { nodelay, socket buffer 65536 }
}
-relay sshforward {
- protocol myssh
+relay "sshforward" {
listen on www.example.com port 2222
+ protocol "myssh"
forward to shell.example.com port 22
}
.Ed
@@ -953,8 +986,14 @@ relay sshforward {
.Sh HISTORY
The
.Nm
-file format first appeared in
+file format, formerly known as
+.Ic hoststated.conf ,
+first appeared in
.Ox 4.1 .
+It was renamed to
+.Nm
+in
+.Ox 4.3 .
.Sh AUTHORS
.An -nosplit
The
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index d52970db906..f0f682a004d 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.87 2007/12/07 17:17:01 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.88 2007/12/08 17:07:09 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -542,7 +542,6 @@ struct relay_config {
in_port_t port;
in_port_t dstport;
int dstmode;
- int dstcheck;
int dstretry;
objid_t dsttable;
struct sockaddr_storage ss;
@@ -586,7 +585,7 @@ enum dstmode {
RELAY_DSTMODE_ROUNDROBIN = 1,
RELAY_DSTMODE_HASH = 2
};
-#define RELAY_DSTMODE_DEFAULT RELAY_DSTMODE_LOADBALANCE
+#define RELAY_DSTMODE_DEFAULT RELAY_DSTMODE_ROUNDROBIN
enum {
PROC_MAIN,
@@ -781,6 +780,7 @@ struct table *table_find(struct relayd *, objid_t);
struct service *service_find(struct relayd *, objid_t);
struct host *host_findbyname(struct relayd *, const char *);
struct table *table_findbyname(struct relayd *, const char *);
+struct table *table_findbyconf(struct relayd *, struct table *);
struct service *service_findbyname(struct relayd *, const char *);
void event_again(struct event *, int, short,
void (*)(int, short, void *),
@@ -791,6 +791,7 @@ struct relay *relay_findbyname(struct relayd *, const char *);
int expand_string(char *, size_t, const char *, const char *);
void translate_string(char *);
void purge_config(struct relayd *, u_int8_t);
+void purge_table(struct tablelist *, struct table *);
void merge_config(struct relayd *, struct relayd *);
char *digeststr(enum digest_type, const u_int8_t *, size_t, char *);
const char *canonicalize_host(const char *, char *, size_t);