一文打盡端口復用 VS Haproxy端口復用

出品|MS08067實驗室(www.ms08067.com)

本文作者:Spark(Ms08067內網安全小組成員)

1.概述

  Haproxy是一個使用c語言開發的高性能負載均衡代理軟件,提供tcp和http的應用程序代理,免費、快速且可靠。
  類似frp,使用一個配置文件+一個server就可以運行。

優點:

  • 大型業務領域應用廣泛
  • 支持四層代理(傳輸層)以及七層代理(應用層)
  • 支持acl(訪問控制列表),可靈活配置路由
  • windows使用cygwin編譯後可運行(可跨平台)

  訪問控制列表(Access Control Lists,ACL)是應用在路由器接口的指令列表,這些指令列表用來告訴路由器哪些數據包可以接受,哪些數據包需要拒絕。

2.配置

  官方配置手冊:
  //cbonte.github.io/haproxy-dconv/2.2/configuration.html
  配置文件由全局配置和代理配置組成:

全局配置(global):

  • 定義haproxy進程管理安全及性能相關的參數

代理設定(proxies):

  • defaults
    • 為其他配置段提供默認參數,默認配置參數可由下一個”defaults”重新設定
  • frontend
    • 定義一系列監聽的套接字,這些套接字可接受客戶端請求並與之建立連接
  • backend
    • 定義”後端”服務器,前端代理服務器將會把哭護短的請求調度至這些服務器
  • listen
    • 定義監聽的套接字和後端的服務器,類似於將frontend和backend段放在一起

示例:

global
defaults
  log global
  mode tcp
  option dontlognull
  timeout connect 5000
  timeout client 50000
  timeout server 50000

frontend main
  mode tcp
  bind *:8888
  option forwardfor except 127.0.0.1
  option forwardfor header X‐Real‐IP

# 配置acl規則
  acl is‐proxy‐now urlp_reg(proxy) ^(http|https|socks5)$
# 分發到對應的backend
  use_backend socks5 if is‐proxy‐now
  use_backend http
backend socks5
  mode tcp
  timeout server 1h
  server ss 127.0.0.1:50000
backend http
  mode tcp
  server http 127.0.0.1:80

  重點關注frontend和backend。
  Frontend中需要編寫acl規則,配置轉發。比如,當http流量來的時候,轉發給web服務;當rdp流量來的時候,轉發給rdp服務。
  Backend中需要編寫具體的操作,就是轉達到哪個目標的哪個端口。

3.思路

(1) 思路一(通用)

  編寫acl規則,在四層(傳輸層)進行負載,根據協議類型進行分發,例如:遇到http流量發送給http服務,遇到rdp發送給rdp服務等。

(2) 思路二

  編寫acl規則,在七層(應用層)進行負載,判斷應用類型進行分發,例如,遇到http分發到http服務,否則發送到xxx服務。

4.步驟

以思路一為例:

  1. 通過wireshark捕獲tpkt(應用層數據傳輸協議)信息
  2. 編寫acl規則路由進行流量分發
  3. 添加後端server
  4. 原始接口接管
  5. 完成

4.1 捕獲tpkt

  關於tpkt可百度或查看參考鏈接
  三次握手後,開始應用層數據傳輸。
  使用wireshark抓包:
ssh協議:

  前三個包為三次握手,第四個包的起始三位,便是我們需要的tpkt,例如ssh為535348。
rdp協議:030000

速查:

協議 TPKT
SSH 535348
RDP 030000
HTTP(GET) 474554
HTTP(POS) 504f53
HTTP(PUT) 505554
HTTP(DEL) 44454c
HTTP(OPT) 4f5054
HTTP(HEA) 484541
HTTP(CON) 434f4e
HTTP(TRA) 545241
HTTPS 160301

4.2 編寫acl規則

global
defaults
  timeout connect 5000
  timeout client 50000
  timeout server 50000
frontend main
  mode tcp
  bind *:8888
# 重點:編寫acl規則進行轉發
  tcp‐request inspect‐delay 3s
  acl is_http req.payload(0,3) ‐m bin 474554 504f53 505554 44454c 4f5054 484541 434f4e 545241
  acl is_ssh req.payload(0,3) ‐m bin 535348
  acl is_rdp req.payload(0,3) ‐m bin 030000
# 設置四層允許通過
  tcp‐request content accept if is_http
  tcp‐request content accept if is_ssh
  tcp‐request content accept if is_rdp
  tcp‐request content accept
# 分發到對應的backend
  use_backend http if is_http
  use_backend ssh if is_ssh
  use_backend rdp if is_rdp
  use_backend socks5
backend socks5
  mode tcp
  timeout server 1h
  server ss 127.0.0.1:50000
backend http
  mode tcp
  server http 127.0.0.1:80
backend ssh
  mode tcp
  server ssh 127.0.0.1:22
backend rdp
  mode tcp
  server rdp 192.168.213.129:3389

  該配置文件的功能是監聽8888端口,將http流量(速查表中http協議的8種tpkt)轉發到本地的80上,將ssh流量轉發到本地的22端口上,將rdp流量轉發到另一主機的3389上。

5.實驗

  • Target1:Ubuntu 16.04 x64
  • IP:192.168.213.128
  • 開啟22端口、80端口


  • Target2:Win7 x64
  • IP:192.168.213.129
  • 開啟3389端口

  啟動haproxy,-f 指定配置文件,開啟8888端口表示啟動成功。-d:調試模式,可不加。

  HTTP協議:訪問靶機的8888端口,流量被haproxy分發至本機的80。

  RDP協議:訪問靶機的8888端口,流量被haproxy分發至192.168.213.129的3389。

  SSH協議:訪問靶機的8888端口,流量被haproxy分發至本機的22。

  haproxy日誌:

6.端口重定向

  為了不影響正常的80端口的訪問,將過來的80端口流量轉發到8888端口上。這樣用戶正常訪問80端口時,流量會先轉發到8888端口上,再由haproxy轉發回80端口。

  • Linux:iptables(不需要重啟服務)
iptables ‐t nat ‐A PREROUTING ‐i eth0 ‐p tcp ‐‐dport 80 ‐j REDIRECT ‐‐to‐port 8888

  訪問80可以正常訪問:

  Haproxy日誌有記錄,說明流量由80先到8888,再回到80。

  Windows:netsh(需要重啟web服務)

netsh interface portproxy add v4tov4 listenport=80 connectport=8888 connectaddress=127.0.0.1

注意:如果在windows下啟用端口重定向,需要在端口啟動前添加netsh端口轉發規則。

7.參考鏈接

轉載請聯繫作者並註明出處!