포트 443에서 TCP 연결을 수락하고 연결이 OpenVPN 클라이언트인지 HTTPS 클라이언트인지 확인한 다음 이를 내 웹 서버 또는 OpenVPN 서버로 전달해야 하는 서버가 있습니다.
SSLH는 이러한 목적을 위해 특별히 설계되었으며 매우 잘 작동하는 것 같습니다. 유일한 문제는 불투명 모드로 설정하면 문제가 없지만 투명 모드를 사용하면 문제가 발생한다는 것입니다.
투명 모드가 어떻게 작동해야 하는지에 대한 이론을 설명할 수 있는 사람이 있나요?
이것SSLH 가이드에는 SSLH를 투명하게 사용하기 위해, 다음을 수행해야 합니다.
- sslh.cfg를 다음으로 설정합니다.
transparent: true;
- 나는 이미 이것을 했다
- SSLH에는 확장 권한(CAP_NET_ADMIN)이 필요합니다.
- systemd용 sslh.service와 함께 제공되는 CentOS 7 저장소에서 sslh를 설치했습니다. 서비스 파일에는 행이 포함되어
CapabilityBoundingSet=... CAP_NET_ADMIN ...
있으므로 SystemD에서 이미 수행했다고 가정합니다.
- systemd용 sslh.service와 함께 제공되는 CentOS 7 저장소에서 sslh를 설치했습니다. 서비스 파일에는 행이 포함되어
- 패킷 및 일종의 로컬 라우팅을 표시하기 위해 iptables 규칙을 설정하십시오.
- 이건 잘 모르겠습니다. SSLH 서버에 설정되어 있습니까? 아니면 OpenVPN 및 HTTPS 서버에 설정합니까?
예제에서 iptables는 소스 포트가 22 또는 4443인 모든 패킷을 0x1 태그로 표시하고, 0x1 태그가 있는 모든 패킷이 경로 테이블 100을 사용하도록 규칙을 생성하고, 경로 테이블 100을 생성하여 일부를 설정하라는 지시를 받았다는 것을 이해합니다. 일종의 특정 작업을 수행하는 로컬 경로입니다.
이러한 iptables 규칙과 라우팅이 필요한 이유는 무엇입니까? 실제로 경로는 무엇을 하고 있나요? 나는 라우팅이 웹 서버와 OpenVPN 서버에 있어야 하고 SSLH IP를 가리켜야 한다고 생각했지만 그것도 나에게는 작동하지 않는 것 같습니다.
===
업데이트: 예제에서 서버는 모두 동일한 시스템에 있고 실제 서버의 응답 패킷이 떠나기 전에 SSLH 시스템을 통과하기를 원하기 때문에 이것이 localhost에 대한 경로일 수 있다는 생각이 들었습니다. 맞는 것 같나요? 그렇다면 내 서버가 다른 컴퓨터에 있으면 어떻게 해야 합니까? 이 시스템에서 SSLH 서버로 트래픽 표시 및 라우팅을 다시 설정하시겠습니까?
업데이트 2: SSLH와 동일한 시스템에 HTTPS 서버를 빠르게 설정했는데 투명 모드가 SSLH 문서 예제에서와 같이 작동하는 것 같습니다. 다른 서버에 있을 때 작동하려면 이것이 필요합니다.
답변1
불투명 모드에서 클라이언트는 포트의 프록시 client_ip:client_port
에 연결됩니다 . 그런 다음 프록시는 해당 포트에서 내부 서버에 대한 연결을 엽니다 . 내부 웹 서버가 에서 응답합니다. 마지막으로 프록시는 응답 패킷의 소스를 다시 작성하여 클라이언트에 보냅니다.sslh
443
sslh
sslh_ip:sslh_port
4443
web_ip:4443
proxy_ip:proxy_port
sslh
sshl_ip:443
투명 모드에서는 sslh
프록시와 내부 서버 간의 연결을 위한 패킷 소스가 원시 패킷으로 설정됩니다 client_ip:client_port
. 따라서 내부 웹 서버는 소스 client_ip:client_port
로 직접 응답합니다. web_ip:4443
그러나 클라이언트는 패킷이 형성될 때까지 기다립니다 proxy_ip:443
.
내부 서버의 응답 패킷 다시 쓰기를 관리하려면 이러한 패킷이 sslh
데몬을 통해 라우팅되어야 합니다. 데몬이 루프백 인터페이스에서 클라이언트에 대한 응답 패킷을 찾고 있는 것 같습니다. 설명서에는 sslh
프록시와 웹 내부 서버가 동일한 컴퓨터에 있다는 것만 명시되어 있습니다.
시행착오를 통해 다음 해결책을 찾았습니다. ( sslh
프록시에서)
ip route add local default dev lo table 100
ip rule add fwmark 0x1 lookup 100
iptables -t mangle -N SSLH
iptables -t mangle -A SSLH -j MARK --set-mark 0x1
iptables -t mangle -A SSLH -j ACCEPT
(내부 서버로부터 응답 패킷 캡처)
iptables -t mangle -A PREROUTING -p tcp -s **web_ip** --sport 4443 -j SSLH
...(ssh, openvpn과 같은 다른 서비스에 대한 유사한 규칙)...
sshl
이 기능은 내부 웹 서버의 기본 경로가 프록시 서버를 통해 인터넷에 연결되는 경우 에만 작동합니다.
답변2
Norbert에게 감사드립니다. 일반적인 아이디어를 아주 잘 설명하셨습니다. 요약하자면, 제가 알 수 있는 한, 우리가 실행 중인 모든 명령에서 구체적으로 일어나는 일은 다음과 같습니다.
SSLH 서버:
$ sudo iptables -t mangle -N SSLH
$ sudo iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j SSLH
$ sudo iptables -t mangle -A SSLH -j MARK --set-mark 0x1
$ sudo iptables -t mangle -A SSLH -j ACCEPT
$ sudo ip rule add fwmark 0x1 lookup 100
$ sudo ip route add local 0.0.0.0/0 dev lo table 100
내부 웹 서버:
$ sudo iptables -t mangle -N SSLH
$ sudo iptables -t mangle -A OUTPUT -o eth0 -p tcp -m tcp --sport 4443 -j SSLH
$ sudo iptables -t mangle -A SSLH -j MARK --set-mark 0x1
$ sudo iptables -t mangle -A SSLH -j ACCEPT
$ sudo ip rule add fwmark 0x1 lookup 100
$ sudo ip route add default via [SSLH_IP] table 100
내부 웹 서버에서:
- 웹 서버(예: Apache 또는 nginx)가 포트 4443에서 수신 대기 중입니다.
- 소스 포트 4443을 사용하여 eth0에서 전송된 모든 항목은 SSLH 체인으로 전송됩니다.
- SSLH 체인의 모든 항목은 0x1로 표시됩니다.
- 0x1 태그가 지정된 모든 항목은 기본 라우팅 테이블 대신 라우팅 테이블 100을 사용해야 한다는 라우팅 규칙을 만듭니다.
- 라우팅 테이블 100에는 트래픽이 기본 게이트웨이 대신 SSLH 서버로 전송됨을 나타내는 항목이 있습니다.
이 일련의 이벤트는 기본적으로 웹 서버 프로세스(nginx/apache/기타)의 트래픽이 나머지 시스템 트래픽처럼 기본 게이트웨이로 라우팅되는 대신 SSLH 서버로 라우팅되도록 강제합니다.
SSLH 서버에서:
- 웹 서버(소스 포트 4443)에서 들어오는 모든 항목은 SSLH 체인으로 전송됩니다.
- SSLH 체인의 모든 항목은 0x1로 표시됩니다.
- 0x1 태그가 지정된 모든 항목은 기본 라우팅 테이블 대신 라우팅 테이블 100을 사용해야 한다는 라우팅 규칙을 만듭니다.
- 경로 테이블 100에는 이 경로 테이블을 사용하는 모든 트래픽을 강제로 루프백 인터페이스로 리디렉션하는 항목이 있습니다.
이러한 일련의 이벤트는 기본적으로 내부 웹 서버의 트래픽이 SSLH 서버의 루프백 인터페이스로 리디렉션되도록 강제합니다. 여기서 SSLH 프로세스는 소스 IP와 포트를 다시 작성하여 전송합니다.
아직 질문이 있습니다.
- 맞는 것 같나요?
- 무엇을 합니까
iptables -t mangle -A SSLH -j ACCEPT
? 그게 필요 할까? 이것은 FILTER 테이블이 아닙니다. 여기서 트래픽을 허용하는 이유는 무엇입니까? - 내 경우에는 SSLH 호스트의 iptables 사전 경로 규칙이 Norbert의 규칙과 다르게 보입니다. 어떻게 작동하나요? 뭔가가 존재하는지 어떻게 알 수 있나요
--transparent
?
답변3
나는 GitHub의 문서화 단계를 따랐습니다(https://github.com/yrutschle/sslh/blob/master/doc/config.md), --transparent
파일의 매개변수를 사용합니다 /etc/default/sslh
.
예를 들어 Apache가 443 대신 포트 4443을 수신하고 있고 OpenVPN도 사용하는 경우:
DAEMON_OPTS="--user sslh --transparent --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:4443 --openvpn 127.0.0.1:1194 --pidfile /var/run/sslh/sslh.pid"
VPN IP 주소로 바꾸고 127.0.0.1:1194
그 뒤에 :1194
(https://github.com/yrutschle/sslh/issues/83#issuecomment-515675186).
IPv6 지원이 필요한 경우 0.0.0.0을 원격 IPv4/IPv6을 가리키는 "이중 스택" 도메인 이름으로 바꾸고, 127.0.0.1을 localhost
로컬 IPv4/IPv6을 가리키는 이름으로 바꿀 수 있습니다( /etc/hosts
.
post-up
Debian에서 재부팅 시 이를 영구적으로 만들려면 기존 구성 아래에 로컬 인터페이스에 대한 다음 규칙을 추가 해야 했습니다 ./etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback
# Configure routing for those marked packets (required by sslh transparent mode for IPv4)
post-up ip rule add fwmark 0x1 lookup 100
post-up ip route add local 0.0.0.0/0 dev lo table 100
iface lo inet6 loopback
# Configure routing for those marked packets (required by sslh transparent mode for IPv6)
post-up ip -6 rule add fwmark 0x1 lookup 100
post-up ip -6 route add local ::/0 dev lo table 100
이러한 규칙은 다음과 같습니다 /etc/sysctl.conf
.
# Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination (required by sslh transparent mode)
net.ipv4.conf.default.route_localnet=1
net.ipv4.conf.all.route_localnet=1
문서에는 영구적으로 사용할 수 있는 몇 가지 iptables 규칙도 있습니다 iptables-persistent
(이유는 모르겠지만 테스트했을 때 투명 모드는 이러한 규칙 없이 작동하는 것 같았습니다).
# 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
IPv6의 경우:
# 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