mirror of
https://github.com/moparisthebest/sslh
synced 2025-02-16 06:50:14 -05:00
Transparant proxy support for FreeBSD
This commit is contained in:
commit
56fdc6b4af
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
VERSION=$(shell ./genver.sh -r)
|
VERSION=$(shell ./genver.sh -r)
|
||||||
USELIBCONFIG=1 # Use libconfig? (necessary to use configuration files)
|
USELIBCONFIG=1 # Use libconfig? (necessary to use configuration files)
|
||||||
USELIBWRAP= # Use libwrap?
|
USELIBWRAP?= # Use libwrap?
|
||||||
USELIBCAP= # Use libcap?
|
USELIBCAP= # Use libcap?
|
||||||
COV_TEST= # Perform test coverage?
|
COV_TEST= # Perform test coverage?
|
||||||
PREFIX=/usr/local
|
PREFIX=/usr/local
|
||||||
|
39
README.md
39
README.md
@ -217,13 +217,15 @@ transparent proxying, just don't use it (or use the libcap method).
|
|||||||
Transparent proxy support
|
Transparent proxy support
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
On Linux (only?) you can use the `--transparent` option to
|
On Linux and FreeBSD you can use the `--transparent` option to
|
||||||
request transparent proying. This means services behind `sslh`
|
request transparent proying. This means services behind `sslh`
|
||||||
(Apache, `sshd` and so on) will see the external IP and ports
|
(Apache, `sshd` and so on) will see the external IP and ports
|
||||||
as if the external world connected directly to them. This
|
as if the external world connected directly to them. This
|
||||||
simplifies IP-based access control (or makes it possible at
|
simplifies IP-based access control (or makes it possible at
|
||||||
all).
|
all).
|
||||||
|
|
||||||
|
Linux:
|
||||||
|
|
||||||
`sslh` needs extended rights to perform this: you'll need to
|
`sslh` needs extended rights to perform this: you'll need to
|
||||||
give it `CAP_NET_ADMIN` capabilities (see appropriate chapter)
|
give it `CAP_NET_ADMIN` capabilities (see appropriate chapter)
|
||||||
or run it as root (but don't do that).
|
or run it as root (but don't do that).
|
||||||
@ -241,6 +243,41 @@ this scheme -- let me know if you manage that:
|
|||||||
# ip rule add fwmark 0x1 lookup 100
|
# ip rule add fwmark 0x1 lookup 100
|
||||||
# ip route add local 0.0.0.0/0 dev lo table 100
|
# ip route add local 0.0.0.0/0 dev lo table 100
|
||||||
|
|
||||||
|
FreeBSD:
|
||||||
|
|
||||||
|
Given you have no firewall defined yet, you can use the following configuration
|
||||||
|
to have ipfw properly redirect traffic back to sslh
|
||||||
|
|
||||||
|
/etc/rc.conf
|
||||||
|
firewall_enable="YES"
|
||||||
|
firewall_type="open"
|
||||||
|
firewall_logif="YES"
|
||||||
|
firewall_coscripts="/etc/ipfw/sslh.rules"
|
||||||
|
|
||||||
|
|
||||||
|
/etc/ipfw/sslh.rules
|
||||||
|
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# ssl
|
||||||
|
ipfw add 20000 fwd 192.0.2.1,443 log tcp from 192.0.2.1 8443 to any out
|
||||||
|
ipfw add 20010 fwd 2001:db8::1,443 log tcp from 2001:db8::1 8443 to any out
|
||||||
|
|
||||||
|
# ssh
|
||||||
|
ipfw add 20100 fwd 192.0.2.1,443 log tcp from 192.0.2.1 8022 to any out
|
||||||
|
ipfw add 20110 fwd 2001:db8::1,443 log tcp from 2001:db8::1 8022 to any out
|
||||||
|
|
||||||
|
# xmpp
|
||||||
|
ipfw add 20200 fwd 192.0.2.1,443 log tcp from 192.0.2.1 5222 to any out
|
||||||
|
ipfw add 20210 fwd 2001:db8::1,443 log tcp from 2001:db8::1 5222 to any out
|
||||||
|
|
||||||
|
# openvpn (running on other internal system)
|
||||||
|
ipfw add 20300 fwd 192.0.2.1,443 log tcp from 198.51.100.7 1194 to any out
|
||||||
|
ipfw add 20310 fwd 2001:db8::1,443 log tcp from 2001:db8:1::7 1194 to any out
|
||||||
|
|
||||||
|
General notes:
|
||||||
|
|
||||||
|
|
||||||
This will only work if `sslh` does not use any loopback
|
This will only work if `sslh` does not use any loopback
|
||||||
addresses (no `127.0.0.1` or `localhost`), you'll need to use
|
addresses (no `127.0.0.1` or `localhost`), you'll need to use
|
||||||
explicit IP addresses (or names):
|
explicit IP addresses (or names):
|
||||||
|
27
common.c
27
common.c
@ -120,8 +120,20 @@ int bind_peer(int fd, int fd_from)
|
|||||||
* got here */
|
* got here */
|
||||||
res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
|
res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
|
||||||
CHECK_RES_RETURN(res, "getpeername");
|
CHECK_RES_RETURN(res, "getpeername");
|
||||||
|
#ifndef IP_BINDANY /* use IP_TRANSPARENT */
|
||||||
res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &trans, sizeof(trans));
|
res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &trans, sizeof(trans));
|
||||||
CHECK_RES_DIE(res, "setsockopt");
|
CHECK_RES_DIE(res, "setsockopt");
|
||||||
|
#else
|
||||||
|
if (from.ai_addr->sa_family==AF_INET) { /* IPv4 */
|
||||||
|
res = setsockopt(fd, IPPROTO_IP, IP_BINDANY, &trans, sizeof(trans));
|
||||||
|
CHECK_RES_RETURN(res, "setsockopt IP_BINDANY");
|
||||||
|
#ifdef IPV6_BINDANY
|
||||||
|
} else { /* IPv6 */
|
||||||
|
res = setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &trans, sizeof(trans));
|
||||||
|
CHECK_RES_RETURN(res, "setsockopt IPV6_BINDANY");
|
||||||
|
#endif /* IPV6_BINDANY */
|
||||||
|
}
|
||||||
|
#endif /* IP_TRANSPARENT / IP_BINDANY */
|
||||||
res = bind(fd, from.ai_addr, from.ai_addrlen);
|
res = bind(fd, from.ai_addr, from.ai_addrlen);
|
||||||
CHECK_RES_RETURN(res, "bind");
|
CHECK_RES_RETURN(res, "bind");
|
||||||
|
|
||||||
@ -134,15 +146,28 @@ int bind_peer(int fd, int fd_from)
|
|||||||
* of new file descriptor. */
|
* of new file descriptor. */
|
||||||
int connect_addr(struct connection *cnx, int fd_from)
|
int connect_addr(struct connection *cnx, int fd_from)
|
||||||
{
|
{
|
||||||
struct addrinfo *a;
|
struct addrinfo *a, from;
|
||||||
|
struct sockaddr_storage ss;
|
||||||
char buf[NI_MAXHOST];
|
char buf[NI_MAXHOST];
|
||||||
int fd, res;
|
int fd, res;
|
||||||
|
|
||||||
|
memset(&from, 0, sizeof(from));
|
||||||
|
from.ai_addr = (struct sockaddr*)&ss;
|
||||||
|
from.ai_addrlen = sizeof(ss);
|
||||||
|
|
||||||
|
res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
|
||||||
|
CHECK_RES_RETURN(res, "getpeername");
|
||||||
|
|
||||||
for (a = cnx->proto->saddr; a; a = a->ai_next) {
|
for (a = cnx->proto->saddr; a; a = a->ai_next) {
|
||||||
|
/* When transparent, make sure both connections use the same address family */
|
||||||
|
if (transparent && a->ai_family != from.ai_addr->sa_family)
|
||||||
|
continue;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "connecting to %s family %d len %d\n",
|
fprintf(stderr, "connecting to %s family %d len %d\n",
|
||||||
sprintaddr(buf, sizeof(buf), a),
|
sprintaddr(buf, sizeof(buf), a),
|
||||||
a->ai_addr->sa_family, a->ai_addrlen);
|
a->ai_addr->sa_family, a->ai_addrlen);
|
||||||
|
|
||||||
|
/* XXX Needs to match ai_family from fd_from when being transparent! */
|
||||||
fd = socket(a->ai_family, SOCK_STREAM, 0);
|
fd = socket(a->ai_family, SOCK_STREAM, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
log_message(LOG_ERR, "forward to %s failed:socket: %s\n",
|
log_message(LOG_ERR, "forward to %s failed:socket: %s\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user