tomcat ip白名单(二)openshift无法同时支持http和https tunnel(http+tcp),方案一流产
1 openshift 背景,为什么项目二(http springboot用https域名访问)与项目一(双向ssl透传)可以共存
* edge - TLS termination is done by the router and http is used to communicate with the backend (default) * passthrough - Traffic is sent straight to the destination without the router providing TLS termination * reencrypt - TLS termination is done by the router and https is used to communicate with the backend
对于本身http的springboot,用edge,对于需要双向ssl的,用passthrough,让它原封不动传递tcp pack,像f5负载均衡
2
2.1 虚拟机暴露20000到外部,原服务为http springboot起在20001
2.2 用passthrough,后再关掉tls
对http非CONNECT包,认定为原服务,把http流量转发到localhost 20001——内网外网均成功,通过浏览器访问http。。。成功
对http CONNECT包,认定为代理请求,拿下host和port保存在channelHandler——外网失败,内网成功
对tcp包,认定为代理请求后续包,转发——测不到,网关为http模式,即使CONNECT成功了,后续估计也会拦截了它认不出的tcp包
3 openshift和haproxy层面解决方案
3.0 原因
开passthough,http协议不支持,https可以访问原服务,代理CONNECT无反应
关https,https协议不支持,http可以访问原服务,https代理没反应,连CONNECT都没收到,第一层应该就被拦截了
推测为haproxy原生不支持connect协议,就像nginx要装一个东西 (正向代理)
同时,开启https后,网关可能希望第一个包是ClientHello,而Connect没有这个
3.1 实际需求一
https://stackoverflow.com/questions/62166972/is-there-a-way-to-use-a-forwarding-proxy-as-a-backend-including-authentication
Is there a way to use a forwarding proxy as a backend (including authentication) in HAProxy?
I am quite new to HAProxy and want to achieve the following setup / packet flow:
Client -> HAProxy (as reverse proxy) -> Forwarding Proxy (HAProxy, IIS, Squid...) -> Internet -> server.example.com
I would like to have encrypted connections with TLS/SSL from the Client -> HAProxy
and from HAProxy -> server.example.com
This means, that the forwarding proxy needs to support the HTTP CONNECT method, to establish a TCP tunnel and transmits packets without trying to interpret them. Over this TCP port I should be able to send bytes to server.example.com
- TLS/SSL encrypted, so HTTPS.
Furthermore it could be, that authentication against the forwarding proxy is needed e.g. HTTP Basic authentication.
The software stack of my test setup is as follows:
Client Firefox 76.0.1
HA-Proxy version 1.6.3 2015/12/25
Squid Cache: Version 3.5.27
I have setup this HAProxy configuration:
global
# Standard settings
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
# Tuning
maxconn 2000
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-options no-sslv3
# Ensure a secure enough DH paramset
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
# Redispatch 503 errors on backends, reducing the number of 503 reaching clients
option redispatch
# We want to stall clients for as long as possible, before giving
# up with 503:
timeout connect 5m
# Clients must be acceptably responsive
timeout client 1m
# Server not as much...
timeout server 5m
# HTTPS server
frontend https-in
bind :443 ssl crt-ignore-err all crt /etc/haproxy/ssl/certkey.pem
# Don't serve HTTP directly, but redirect to same URL in https
redirect scheme https code 301 if !{ ssl_fc }
default_backend backend-proxy
backend backend-proxy
# Create the Authorization / Proxy-Authorization header value
# echo -n "user:password" | base64
http-request add-header Proxy-Authorization "Basic dXNlcjpwYXNzd29yZA=="
# We need to use the CONNECT method
http-request set-method CONNECT
# The proxyserver needs to know the full server name
http-request set-path server.example.com:443
server proxy 192.168.1.1:8080
In my test setup I use a Squid
server as a forwarding proxy with the following configuration:
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 443 # https
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid/squid-passwd
acl basic_client proxy_auth REQUIRED
http_access deny !basic_client
http_access allow basic_client
http_access deny all
http_port 8080
coredump_dir /var/spool/squid
Using the Squid
forwarding proxy in a regular browser on the same subnet including authentication works fine.
So when the first request comes in from the Client
at the HAProxy
it gets forwarded via the backend backend-proxy
to the Forward Proxy (Squid)
. The CONNECT succeeds, as I see in the Squid
log.
1591166403.966 60146 192.168.1.10 TCP_TUNNEL/200 39 CONNECT server.example.com:443 test HIER_DIRECT/6.7.8.9 -
(IP addresses were replaced with generic values)
The HAProxy
log shows, that the correct backend is used:
Jun 3 08:39:57 localhost haproxy[3547]: 192.168.1.20:39398 [03/Jun/2020:08:38:56.855] https-in~ backend-proxy/proxy 154/0/13/209/60375 200 39 - - ---- 0/0/0/0/0 0/0 "GET /someurl HTTP/1.1"
(IP addresses were replaced with generic values)
So far so good. But I am unable to establish a successful communication to server.example.com
from my Client
. I think I have to use a second/other backend, which will not mangle the requests any more (exchange method
and path
) but instead use the given TCP port from the forwarding proxy to transmit the request.
How can I save the 'state' of the communication to my backend / proxy server in HAProxy, so the request could be resend to another backend?
How to extract and use the TCP port from the response of the Forwarding Proxy
?
Is there a way to check, if the TCP tunnel on the Forwarding Proxy
is still opened or do I need to request it using CONNECT
every time before I want to use it?
EDIT: I solved the situation by using stunnel
as an intermediary to handle the TCP tunnel creation with CONNECT against the Forwarding Proxy.
If you have an upstream HTTP proxy (like squid) (not a socks proxy) and you want to have haproxy accept connections and open the tunnel thru the upstream proxy (such that the haproxy clients do not support doing so themselves via http/CONNECT method) on behalf of the clients, then this functionality does not exist in haproxy today.
I crated a branch that does this via server keyword proxy-tunnel
.
The below example config will behave such that clients of haproxy that connect to port 20025
(haproxy) will result in haproxy establishing a http/CONNECT tunnel via the upstream proxy 172.16.0.99:50443
to 172.16.0.2:2023
:
listen SMTP-20025
bind 0.0.0.0:20025
server TEST_SERVERVIA_PROXY 172.16.0.2:2023 proxy-tunnel 172.16.0.99:50443
3.2 另一个实例
https://blog.csdn.net/weixin_34062469/article/details/91523508
stunnel+haproxy SSL以及问题记录
最近在用stunnel做透明代理,配合haproxy做ssl方案,在用户和原有的反向代理之间加入stunnel,这样可以让用户和stunnel之间走ssl,stunnel之后的真实web就不用负担https的开销。
首先先去stunnel官网上获取安装包,因为要给stunnel打haproxy的补丁,而haproxy官方提供的补丁目前版本是4.32的,所以stunnel选择4.32版本,官方提供的ftp上可以找
4 方案二
要自己在https的标准框架下实现CONNECT协议,key在于在双方握手的第一步中,把host和port拿到
两篇比较全的文章
https://halfrost.com/https-extensions/ HTTPS 温故知新(六) —— TLS 中的 Extensions
TLS 没有为 Client 提供一种机制来告诉 Server 它正在建立链接的 Server 的名称。Client 可能希望提供此信息以促进与在单个底层网络地址处托管多个“虚拟”服务的 Server 的安全连接。
当 Client 连接 HTTPS 网站的时候,解析出 IP 地址以后,就能创建 TLS 连接,在握手完成之前,Server 接收到的消息中并没有 host HTTP 的头部。如果这个 Server 有多个虚拟的服务,每个服务都有一张证书,那么此时 Server 不知道该用哪一张证书。
https://blog.csdn.net/xichenguan/article/details/81283029 HTTPS & TLS Extensions
所以侵入点在哪儿,随机数,SNI,还是其他extensions?
5 remote addr做文章
host显然不能伪造,不然直接突破4层白名单了