Hi everybody,
I try to connect to an SSH process via proxytunnel. The incoming request carries normal HTTP headers that I have to skip those in order to forward further encrypted SSH traffic to an SSH process. I thought I could tackle this task using Lua and register_action, but since it’s my first time working with Lua and haproxy and I got stuck. I hope someone could help me on this topic.
### Output:
Apr 08 10:15:48 HOST docker[4059]: [info] 098/101548 (12) : connect-ssh
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : CONNECT 127.0.0.1:22 HTTP/1.1..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : Host: FQDN..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : Proxy-Connection: Keep-Alive..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : X-Forwarded-Proto: https..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : X-Forwarded-For: IP..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : ..
Apr 08 10:15:53 HOST docker[4059]: [ALERT] 098/101553 (12) : Lua function 'connect-ssh': yield not allowed.
### haproxy.cfg:
global
lua-load /etc/haproxy/proxytunnel.lua
…
frontend multiplex-ssh-http
bind :80
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content lua.connect-ssh if METH_CONNECT
# Detect SSH connection attempts
acl client_attempts_ssh payload(0,7) -m bin 5353482d322e30
use_backend tcp-ssh if client_attempts_ssh
default_backend http-nginx
backend tcp-ssh
mode tcp
option tcplog
server ssh dockerhost:22
timeout server 2h
…
### proxytunnel.lua:
function string.starts(haystack, needle)
return haystack:sub(1, needle:len()) == needle
end
core.register_action('connect-ssh', { "tcp-req" }, function(txn)
local line = txn.req:getline();
txn:Info("connect-ssh");
if line == nil then
txn:Debug("Got nil, skipping...");
return
elseif not line:starts("CONNECT 127.0.0.1:22 HTTP/1.1") then
txn:Debug("No match, got " .. line .. ", skipping...");
return
end
repeat -- skip headers
txn:Debug(line);
line = txn.req:getline();
until line == nil or line == "";
return
end);
King regards
Florian Aßmann
I try to connect to an SSH process via proxytunnel. The incoming request carries normal HTTP headers that I have to skip those in order to forward further encrypted SSH traffic to an SSH process. I thought I could tackle this task using Lua and register_action, but since it’s my first time working with Lua and haproxy and I got stuck. I hope someone could help me on this topic.
### Output:
Apr 08 10:15:48 HOST docker[4059]: [info] 098/101548 (12) : connect-ssh
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : CONNECT 127.0.0.1:22 HTTP/1.1..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : Host: FQDN..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : Proxy-Connection: Keep-Alive..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : X-Forwarded-Proto: https..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : X-Forwarded-For: IP..
Apr 08 10:15:48 HOST docker[4059]: [debug] 098/101548 (12) : ..
Apr 08 10:15:53 HOST docker[4059]: [ALERT] 098/101553 (12) : Lua function 'connect-ssh': yield not allowed.
### haproxy.cfg:
global
lua-load /etc/haproxy/proxytunnel.lua
…
frontend multiplex-ssh-http
bind :80
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content lua.connect-ssh if METH_CONNECT
# Detect SSH connection attempts
acl client_attempts_ssh payload(0,7) -m bin 5353482d322e30
use_backend tcp-ssh if client_attempts_ssh
default_backend http-nginx
backend tcp-ssh
mode tcp
option tcplog
server ssh dockerhost:22
timeout server 2h
…
### proxytunnel.lua:
function string.starts(haystack, needle)
return haystack:sub(1, needle:len()) == needle
end
core.register_action('connect-ssh', { "tcp-req" }, function(txn)
local line = txn.req:getline();
txn:Info("connect-ssh");
if line == nil then
txn:Debug("Got nil, skipping...");
return
elseif not line:starts("CONNECT 127.0.0.1:22 HTTP/1.1") then
txn:Debug("No match, got " .. line .. ", skipping...");
return
end
repeat -- skip headers
txn:Debug(line);
line = txn.req:getline();
until line == nil or line == "";
return
end);
King regards
Florian Aßmann