Transparent proxy does not work only with IPv6
soramikan opened this issue · comments
I am using sslh
in Transparent mode and all is well with IPv4!
However, it does not work at all with IPv6 with the following error:
ssh
kex_exchange_identification: Connection closed by remote host
https with curl
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443
These work well with the -4
option.
My environment:
sslh-select --version
# sslh-select v1.22c
I'm useing the latest ArchLinux
This is my sslh.cfg
file:
verbose: 0;
foreground: true;
inetd: false;
numeric: false;
transparent: true;
timeout: 2;
user: "sslh";
pidfile: "/run/sslh/sslh.pid";
listen:
(
{
host: "<My external IPv4 address>";
is_udp: false;
port: "443";
},
{
host: "<My external IPv4 address>";
is_udp: false;
port: "443";
}
);
protocols:
(
{ name: "ssh";
service: "ssh";
host: "127.0.0.1";
port: "2222";
is_udp: false;
log_level: 1;
fork: true;
},
{ name: "ssh";
service: "ssh";
host: "[::1]";
port: "2222";
is_udp: false;
log_level: 3;
fork: true;
},
{ name: "tls";
host: "127.0.0.1";
port: "443";
is_udp: false;
log_level: 0;
tfo_ok: true },
{ name: "tls";
host: "[::1]";
port: "443";
is_udp: false;
log_level: 0;
tfo_ok: true },
);
This is a unit file set up the same way as this guide.
#!/bin/zsh
# Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination
sysctl -w net.ipv4.conf.default.route_localnet=1
sysctl -w net.ipv4.conf.all.route_localnet=1
# DROP martian packets as they would have been if route_localnet was zero
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP
iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP
# Mark all connections made by ssl for special treatment (here sslh is run as user "sslh")
iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f
# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f
# Configure routing for those marked packets
ip rule add fwmark 0x1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
# Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination
# Not sure if this is needed for ipv6 though
sysctl -w net.ipv4.conf.default.route_localnet=1
sysctl -w net.ipv4.conf.all.route_localnet=1
# DROP martian packets as they would have been if route_localnet was zero
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
ip6tables -t raw -A PREROUTING ! -i lo -d ::1/128 -j DROP
ip6tables -t mangle -A POSTROUTING ! -o lo -s ::1/128 -j DROP
# Mark all connections made by ssl for special treatment (here sslh is run as user "sslh")
ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f
# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f
# Configure routing for those marked packets
ip -6 rule add fwmark 0x1 lookup 100
ip -6 route add local ::/0 dev lo table 100
Tanks!
We came across this issue in a gemini host that tries to do tls based rules via the hostname for ipv4 and ipv6 and it is probably caused by the problem that you cannot do transparent=true when you switch between ipv6 and ipv6 from the client to the local server, the suggested solution as described in the mail list (https://lists.rutschle.net/mailman/archives/sslh/2016-January/000603.html) is to use a DNS entry to point to the ipv4 and ivp6 address (or a hosts entry) and use that as target host for the protocols entry. this way it tries to connect to either and will choose the right ip version
I kind of would prefer an option to define rules that only match ipv4 or ipv6 to make that more obvious when using either
Thank you, everything worked fine by putting it in the hosts file!