I'm trying to use the HA Proxy aes_gcm_dec converter, but the documentation is sparse to say the least, and I can't find any examples of its use in the community.
I have a client that is sending up a AES GCM 128 encrypted message in an HTTP header, like this:
curl -H "X-Routing-Key: e4+DM/EkJQl4jAAOxNtDZb4dd5Q=" localhost:8000
I'm using HA Proxy to decrypt that header and forward it to the backend server in decrypted form. Here's my frontend config for that:
http-request set-header X-Routing-Key %[req.hdr(X-Routing-Key),b64dec,aes_gcm_dec(128,4+6ONmgZoNex0arqdTr7bA==,Zm9vb2Zvb29mb29wZm9vbw==,4QMQhILaVLC9oxyB8hGoZA==)]
The aead tag is hardcoded on the server for now, based on a simple python script I wrote for generating the encrypted secret. In the future it will probably be passed up by the client -- same with the nonce. Also, note the b64dec converter before the aes_gcm_dec converter. I'm not sure whether or not it's needed. I've tried it both ways and neither works in the current setup.
When I try to do this, HA Proxy silently fails. The header is set to an empty string when it reaches the backend. Even with debug verbosity, HA Proxy doesn't log anything, but clearly something is wrong. Does anyone know what I'm doing wrong here?
I have provided this answer on the HAProxy community Slack chat but in case someone finds this on Google you would do something as follows in HAProxy
http-request set-var(txn.enc) req.hdr(X-Routing-Key),url_dec,b64dec,bytes(32)
http-request set-var(txn.nonce) req.hdr(X-Routing-Key),url_dec,b64dec,bytes(0,16),base64
http-request set-var(txn.aead_tag) req.hdr(X-Routing-Key),url_dec,b64dec,bytes(16,16),base64
http-request set-header X-Routing-Key %[var(txn.enc),aes_gcm_dec(128,txn.nonce,5AbcQVztUg4LYr406puUkw==,txn.aead_tag)]
Make sure your AES output contains the ciphered text, nonce, and aead tag. In the referenced Python it would be something like this:
print("X-Routing-Key: %s" % (base64.b64encode(b"".join([aesCipher.nonce, authTag, ciphertext]))).decode('utf-8'))
Related
I have a scenario where I need to route TCP traffic to a dynamic set of backend servers (Kubernetes pods to be exact but we can ignore that for purposes of this post) through a proxy like HAProxy or nginx. The traffic needs to be routed based on a key (call it the routing_key) provided by the client in the TCP payload.
I see that both nginx and HAProxy support consistent hashing. However, from what I can tell based on HAProxy's manual (see "balance" section), there's no way to perform consistent hashing based on a TCP payload. Payload-based load balancing seems to be limited to L7 HTTP parameters like Header and URI params. This post outlines a method for statically balancing based on string matching a TCP payload, but my case is more dynamic so a true consistent hashing approach is much preferred.
Nginx appears to offer a bit more flexibility in that you can set the hashing value to an arbitrary variable as shown here. This appears to work for both L7 (the "backend" stanza) and L4 (the "stream" stanza). However, I'm a bit hazy on what you are and aren't allowed to do for variables. Does anyone have an example of setting a variable to be a value extracted from the TCP payload and using that for consistent hashing?
Final bonus question: the routing_key value is actually an AES-GCM encrypted value. The proxy server would have access to the key used to decrypt this value. Is it possible to have nginx grab the routing key value from the TCP payload, decrypt it using the known key, and then use that for consistent hashing? Would that involve creating an nginscript module?
In the HAProxy 2.1 can you use aes_gcm_dec(...) in combination with req.payload(...) for such a requirement.
My idea, untested.
listen tcp-in
bind :443 ssl cert
tcp-request inspect-delay 10s
tcp-request session set-var(sess.routingkey) req.payload(0,500)
# for consistent hashing try this
hash-type consistent wt6
use_backend %[var(sess.routingkey),aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]
Here are also the links to the html Documentation.
aes_gcm_dec
req.payload
hash-type consistent ... is described at hash-type
As i know, when client send http request to server, for safety reason we should not send secret param on request url.
A lot of people say we should use body to attach parameter, i do agree
But what if i use header to send them? Is it safe like body? Somebody say it is not safe like body but could not explain why, please help
Thank
Just open debug console in your browser and you will see there are no difference. From TCP perspective, all the request is just a text file with few new lines between headers and body. And once you send requests over not encrypted channel (http), everything can be captured by the man in the middle. No safe place. On hte other hand, if you use https, your connection is encrypted (on lower level - TCP) and both body and headers are safe enough to transsmit sensitive information. The only "wrong" place even on https is URL, as someone behind your shoulder can see your secrets in browser's address bar.
I am trying to upload data from an Arduino to data.sparkfun.com, but somehow it always fails. To make sure that the HTTP request I am sending is correct, I would like to send it from a computer to the server and see if it uploads the correct values.
According to some examples, the request should be formulated like this:
GET /input/publicKey?private_key=privateKey&dht1_t=24.23&dht1_h=42.4&dht2_t=24.48&dht2_h=41.5&bmp_t=23.3&bmp_p=984021 HTTP/1.1\n
Host: 54.86.132.254\n
Connection: close\n
\n
How do I send this request to the server from my computer? Do I just type in the terminal? Im not sure where to start.
Have a look at curl which should be able to handle your needs.
Even easier and more low level is netcat (here is an example on SO)
I've heared that you (in some cases) can prevent timeouts by sending the HTTP-header back to the client before the whole HTTP-body is prepared.
I know that this is impossible using gzip ... but is this possible using HTTPS?
I read in some posts that the secure part of HTTPS is done in the transport-layer (TLS/SSL) - therefore it should be possible, right?
Sorry for mixing gzip in here - it's a completely different level - I know ... and it may is more confusing than giving an example ;)
In HTTP 1.1 it's possible to send the response header before preparing of the body of the response is completed . To do this one normally uses chunked encoding.
Some servers also stream the data as is by not specifying the content length and indicating the end of stream by closing connection, but this is quite a brutal way to do things (chunked encoding was designed exactly for sending the data before it's completely available).
As HTTP(S) is HTTP running over SSL/TLS channel, TLS doesn't affect the above behavior in any way.
Yes, you can do this. HTTPS is just HTTP over an TLS/SSL transport, the HTTP protocol is exactly the same.
I'm still starting out with Lua, and would like to write a (relatively) simple proxy using it.
This is what I would like to get to:
Listen on port.
Accept connection.
Since this is a proxy, I'm expecting HTTP (Get/Post etc..)/HTTPS/FTP/whatever requests from my browser.
Inspect the request (Just to extract the host and port information?)
Create a new socket and connect to the host specified in the request.
Relay the exact request as it was received, with POST data and all.
Receive the response (header/body/anything else..) and respond to the initial request.
Close Connections? I suppose Keep-Alive shouldn't be respected?
I realize it's not supposed to be trivial, but I'm having a lot of trouble setting this up using LuaSockets or Copas --- how do I receive the entire request? Keep receiving until I scan \r\n\r\n? Then how do I pull the post data? and the body? Or accept a "download" file? I read about the "sink", but admittedly didn't understand most of what that meant, so maybe I should read up more on that?
In case it matters, I'm working on a windows machine, using LuaForWindows and am still rather new to Lua. Loving it so far though, tables are simply amazing :)
I discovered lua-http but it seems to have been merged into Xavante (and I didn't find any version for lua 5.1 and LuaForWindows), not sure if it makes my life easier?
Thanks in advance for any tips, pointers, libraries/source I should be looking at etc :)
Not as easy as you may think. Requests to proxies and request to servers are different. In rfc2616 you can see that, when querying a proxy, a client include the absolute url of the requested document instead of the usual relative one.
So, as a proxy, you have to parse incomming requests, modify them, query the appropriate servers, and return response.
Parsing incomming requests is quite complex as body length depends on various parameters ( method, content encoding, etc ).
You may try to use lua-http-parser.