tcp-check expect binary response in second packet in a row - tcp

I am trying to build a TCP checking on my backend servers using HAProxy version 1.5.8.
The behavior should be as follows:
Send binary data to server
Receive ACK as first packet
Receive confirmation data in second packet
So I need to check that after sending binary data I received ACK and after that other binary data in a second packet in a row.
Is it possible to do it with HAProxy.
I am trying to find it in documentation and also trying to create different configurations, unsuccessfully:
option tcp-check
tcp-check connect
tcp-check send-binary 303030303030
tcp-check expect binary 303030303030
Every time I received back from server ACK, connection is terminated by HAProxy with the result that the backend server is down.
EDIT:
I will receive the following:
First packet after sending data
0000 a0 66 10 09 2e 46 9c af ca bb aa 47 08 00 45 00  f...F.¯Ê»ªG..E.
0010 00 28 40 58 40 00 3e 06 d7 04 0a 1e 0b 34 0a 02 .(#X#.>.×....4..
0020 06 20 25 1c d5 80 91 0a f8 87 db 03 25 8f 50 10 . %.Õ...ø.Û.%.P.
0030 01 c9 03 d6 00 00 00 00 00 00 00 00 .É.Ö........
Second packet right after the above
0000 a0 66 10 09 2e 46 9c af ca bb aa 47 08 00 45 00  f...F.¯Ê»ªG..E.
0010 00 39 40 59 40 00 3e 06 d6 f2 0a 1e 0b 34 0a 02 .9#Y#.>.Öò...4..
0020 06 20 25 1c d5 80 91 0a f8 87 db 03 25 8f 50 18 . %.Õ...ø.Û.%.P.
0030 01 c9 2d 2e 00 00 00 0f 30 30 30 30 30 30 42 33 .É-.....000000B3
0040 30 30 43 48 45 43 4b 00CHECK
The first is without any data and I need to check that the second contains 000000.
EDIT2:
PCAP provided:
Normal behavior when communication goes directly from client to server, without HAProxy:
Normal behavior - client to server
Using HAProxy as load balancer, connecting to the same server and checking with the same command, failing to check:
failing check - HAProxy to server
backend configuration:
backend nodes
mode tcp
balance roundrobin
default-server inter 10s fall 3 rise 2
option tcp-check
tcp-check connect
tcp-check send-binary 303030303030423230303035434845434b
tcp-check expect binary 000f30303030303042333030434845434b
server server1 10.30.11.52:9500 check
server server2 10.30.11.52:9501 check
server server3 10.30.11.52:9502 check

Receive ACK as first packet
HA proxy does not work at the raw packet level but at the TCP level. At this level there is no such thing as an ACK as a single packet. There is not even the concept of a packet at this level. Instead there is only the concept of a data stream consisting of the received bytes.
Every time I received back from server ACK, connection is terminated by HAProxy with the result that the backend server is down.
Given that HA proxy does not care about packets with zero payload in the first place it is likely that your "ACK as first packet" is actually some packet which contains an ACK (as almost all TCP packets do) but also contains some payload, but not the one you expect with the "next packet". Since the payload does not match the payload you specify as expected the check fails.
Note that this is only an assumption made based on incomplete information about your "ACK as first packet". To prove the assumption one would actually need to see what is really going on on the wire, for example by having a packet capture.
EDIT#1: after the OP provided a some (undocumented) dump of the packets and some figuring out where the actual IP header in these packets starts (offset 14, i.e. prefixed with layer 2 ethernet header) it is clear that the first packet has no payload which means it gets completely ignored by the check. The second packet then has the following payload of 17 bytes:
0030 00 0f 30 30 30 30 30 30 42 33 ..000000B3
0040 30 30 43 48 45 43 4b 00CHECK
Given that the OP checks for binary 303030303030 but the actual payload is 00 0f 30 30 30 30 30 30 .... the given tcp-check expect ... does not match the actual payload and thus the check fails.
EDIT#2:
After the OP has provided the pcap of a connection without and with haproxy a difference in the behavior of both client/haproxy and server can be seen:
without haproxy:
client sends 2 bytes \x00\x11 to the server followed by 17 bytes \x30\x30....
server replies immediately with 17 bytes \x00\x0f\x30\x30....
with haproxy:
haproxy send 17 bytes \x30\x30... to the server. It does not send the initial 2 bytes \x00\x11 as done by the original server !!!
Server does not reply (except an ACK with no payload). After 6 seconds of inactivity haproxy closes the connection to the server and likely considers the check failed.
In summary: I think the haproxy check fails to send the proper request to the server, i.e. the first 2 bytes are missing. That's why the server will not respond at all and the check will fail after some timeout.

Related

Problem with sending HDLC frames by using GSM modem

I have SL7000 meter and GSM Modem iRZ. When i send by using RS-485 cable - everything work. But when i'm trying to use GSM modem i'm getting issues.
When i send SNRM like this:
7E A0 0A 00 22 00 51 03 93 6A 34 7E
I get normal UA.
But when i try to send SNRM like this:
7E A0 21 00 22 00 51 03 93 6B 21 81 80 12 05 01 80 07 04 00 00 00 02 08 04 00 00 00 01 3D 93 7E (It's from DXDLMSDirector)
I get nothing. Absolutely!
Maybe there is some trick to use hdlc with gsm modem? Maybe special delays or something?
If both of these frames work via the RS-485, and not via the GSM, then there are a couple of possible answers:
1) the addressing you are using is not permitted if this is a seperate port
2) if it is the same port on the meter, then the GSM Modem is not directing traffic to the same RS485 address

Cannot write CIE's IEEE address to IAS zone device

I am using trying to add the following IAS zone devices (from HEIMAN) to my ZCL co-ordinator(CIE) + IoT gateway (from NXP)
emergency button - gets added easily and triggers successfully
door sensor - joins the network but no enrolment process is seen
Q1. Why is it such that one device undergoes enrolment process correctly and the other doesn't? My understanding is that the ZCL stack should do all the enrolment activities. Am I correct?
Q2. I tried writing IEEE address of the CIE to the node's cluster(0x0500) attribute (0x0010) of attribute type (0xf0). But no response. How to tackle this issue?
For a CIE device, the enrolment is more complex and the ZCL stack will not perform this for you (although this may depend on the stack, and any add-on features it provides).
A CIE device may perform its own service discovery using the ZDO Match Descriptor functions. It may send a MatchDescriptorRequest report looking for an IAS server, and you will need to respond with the MatchDescriptorResponse to report that you support this. Typically the request will be looking for the IAS Zone Server cluster (0x500), but you should inspect the packets and respond appropriately. See 2.4.3.1.7 Match_Desc_req, and 2.4.4.1.7 Match_Desc_rsp of the ZigBee specification. If an IAS device is looking for a zone controller, it may not accept any requests until it receives this response, and in fact some devices may leave the network if they don't find the services they are requesting.
Next, it may enrol with the IAS service by sending the ZoneEnrollRequest command, and your application will need to respond to this with the ZoneEnrollResponse to tell the device that it is now enrolled in your system. Refer to 8.2.2.4.2 Zone Enroll Request Command in the ZCL specification.
From your traces, it is hard to say what is happening as the log viewer doesn't provide any information on the contents of the Data Request frames in this view. However, we can see a lot of frames being sent from the device to the coordinator, and it is likely that it is performing one, or both of the discovery services discussed above. You should inspect the requests to find out what they are, and check the appropriate sections of the ZigBee specification, or the ZigBee Cluster Library Specification.
CIE IEEE Address to IAS zone worked successfully. Tested using Xbee s2c.
Explicit Addressing Command Frame (API 2)
7E 00 22 7D 31 01 28 6D 97 00 01 04 2B 7D 5D FF FE E8 01 05 00 01 04 00 20 00 01 02 10 00 F0 6B 7A 29 41 00 A2 7D 33 00 FD
Start delimiter: 7E
Length: 00 22 (34)
Frame type: 11 (Explicit Addressing Command Frame)
Frame ID: 01 (1)
64-bit dest. address: 28 6D 97 00 01 04 2B 7D
16-bit dest. address: FF FE
Source endpoint: E8
Dest. endpoint: 01
Cluster ID: 05 00
Profile ID: 01 04
Broadcast radius: 00 (0)
Transmit options: 20
RF data: 00 01 02 10 00 F0 6B 7A 29 41 00 A2 13 00
Checksum: FD
Explicit RX Indicator (API 2)
7E 00 16 91 28 6D 97 00 01 04 2B 7D 5D A3 87 01 E8 05 00 01 04 21 18 01 04 00 3A
Start delimiter: 7E
Length: 00 16 (22)
Frame type: 91 (Explicit RX Indicator)
64-bit source address: 28 6D 97 00 01 04 2B 7D
16-bit source address: A3 87
Source endpoint: 01
Destination endpoint: E8
Cluster ID: 05 00
Profile ID: 01 04
Receive options: 21
RF data: 18 01 04 00
Checksum: 3A

looking to understand meaning of two bytes in HTTP request made with curl --trace

tl;dr "What would the bytes 0x33 0x39 0x0d 0x0a between the end of HTTP headers and the start of HTTP response body refer to?"
I'm using the thoroughly excellent libcurl to make HTTP requests to various 3rd party endpoints. These endpoints are not under my control and are required to implement a specification. To help debug and develop these endpoints I have implemented the text output functionality you might see if you make a curl request from the command line with the -v flag using curl.setopt(pycurl.VERBOSE, 1) and curl.setopt(pycurl.DEBUGFUNCTION, debug_function)
This has been working great but recently I've come across a request which my debug function does not handle in the same way as curl's debug output. I'm sure is due to me not understanding the HTTP spec.
If making a curl request from the command line with --verbose I get the following returned.
# redacted headers
< Via: 1.1 vegur
<
{"code":"InvalidCredentials","message":"Bad credentials"}*
Connection #0 to host redacted left intact
If making the same request with --trace the following is returned
0000: 56 69 61 3a 20 31 2e 31 20 76 65 67 75 72 0d 0a Via: 1.1 vegur..
<= Recv header, 2 bytes (0x2)
0000: 0d 0a ..
<= Recv data, 1 bytes (0x1)
0000: 33 3
<= Recv data, 62 bytes (0x3e)
0000: 39 0d 0a 7b 22 63 6f 64 65 22 3a 22 49 6e 76 61 9..{"code":"Inva
0010: 6c 69 64 43 72 65 64 65 6e 74 69 61 6c 73 22 2c lidCredentials",
0020: 22 6d 65 73 73 61 67 65 22 3a 22 42 61 64 20 63 "message":"Bad c
0030: 72 65 64 65 6e 74 69 61 6c 73 22 7d 0d 0a redentials"}..
<= Recv data, 1 bytes (0x1)
0000: 30 0
<= Recv data, 4 bytes (0x4)
0000: 0d 0a 0d 0a ....
== Info: Connection #0 to host redacted left intact
All HTTP client libs I've tested don't include these parts of the bytes in the response body so I'm guessing these are part of the HTTP spec I don't know about but I can't find a reference to them and I don't know how to handle them.
If it's helpful I think curl is using this https://github.com/curl/curl/blob/master/src/tool_cb_dbg.c for building the output in the first example bit I'm not really a c/c++ programmer and I haven't been able to reverse engineer the logic.
Does anyone know what these bytes are?
0d 0a are ASCII control characters representing carriage return and line feed, respectively. CRLF is used in HTTP to mark the end of a header field (there are some historic exceptions you should not worry about at this point). A double CRLF is supposed to mark the end of the fields section of a message.
The 33 39 you observe there is "39" in ascii. This is the chunk size indicator - treated as a hexdecimal number. The presence of Transfer-Encoding: chunked in the response headers may support this.

Advertise Bluetooth LE Service using HCITool

I'm experimenting with creating a Bluetooth Low Energy Peripheral on my Linux computer (The goal is to send data over Bluetooth From an iPhone). Im currently using the Tools hciconfig, hcitool and hcidump.
My current experiment is to advertise a Service with a Specific UUID, that the iOS CoreBluetooth Library will pick up. (Note: I'm not trying to create an iBeacon).
Right now, it's actually as simple as One Single Command that is bugging me.
hcitool -i hci0 cmd 0x08 0x0008 15 02 01 1a 11 07 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50
What I think it should do is the following:
0x08: Setting Group to BLE
0x0008: Setting Command to HCI_LE_Set_Advertising_Data
0x15: Setting the Length of the Significant Bytes in the Header to 21. (3 Byte for the Flag packet, 18 Byte for the Service Structure)
0x02: Setting the Length of the Flags structure to 2 Bytes
0x01: Setting the structure Type to AD Flags
0x1a: Flag Value:
bit 0 (OFF) LE Limited Discoverable Mode
bit 1 (ON) LE General Discoverable Mode
bit 2 (OFF) BR/EDR Not Supported
bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
(End of Flag)
0x11 Setting the Length of Service Structure to 17 Bytes
0x07 Setting the Structure Type to 128 Bit Complete Service UUID List
0x41 ... 0x50 Setting the UUID of the Test Service to ABCDEFGHIJKLMNOP
As far as I can see with hcidump, it's executed properly and looks the way I wanted to. But it's rejected with Error:
LE Set Advertising Data (0x08|0x0008) ncmd 1
status 0x12
Error: Invalid HCI Command Parameters
And I have spent a whole day trying to get it right. Does someone skilled see what I have done wrong? And is this the correct way to advertise a Service?
(Context for the Interested reader: I have successfully accomplished what I want to do using the Bleno Library in NodeJs. However, this will not fit into the bigger picture in our System. Using HCITool directly for advertising is just for experimentation and will be written in Python later)
The length of the the HCI_LE_Set_Advertising_Data payload should be exactly 32 bytes. Try zero padding the command to reach 32 bytes:
hcitool -i hci0 cmd 0x08 0x0008 15 02 01 1a 11 07 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 00 00 00 00 00 00 00 00 00 00
You can gain some more insight using hcidump --raw.
Compare the output of the original command:
$hcidump --raw
HCI sniffer - Bluetooth packet analyzer ver 5.30
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
< 01 08 20 16 15 02 01 1A 11 07 41 42 43 44 45 46 47 48 49 4A
4B 4C 4D 4E 4F 50
> 04 0E 04 01 08 2
With the zero padded one:
HCI sniffer - Bluetooth packet analyzer ver 5.30
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
< 01 08 20 20 15 02 01 1A 11 07 41 42 43 44 45 46 47 48 49 4A
4B 4C 4D 4E 4F 50 00 00 00 00 00 00 00 00 00 00
> 04 0E 04 01 08 20 00
Another way to gain more insight is to run hciconfig hci0 leadv and use hcidump --raw to examine the payload of the SET_ADVERTISING_PARAMETERS command send by hciconfig.
By the way, I've noticed that sometimes a non zero padded command also works, it might depend on the bluez version you are using.

What does TLS Handshake Type 174 Mean?

Out of curiosity, I spent some time looking through TCP dumps of an https web connection I made. I have been able to make sense of most of it, but I am stuck on one particular TLS Record. Here is the hex dump:
16 03 01 00 24 ae f5 83 cb 35 db dd 67 f5 bf 4a
c7 52 b5 16 56 59 52 40 fa 7b f8 f6 40 a7 13 74
0a f3 b0 6e 5b 4f 2b 88 a3
The previous Record is a Change Cipher Spec Record (i.e. Content Type 0x14) if that helps. Also, I used wget to make the request.
As far as I can tell, this should follow the handshake subprotocol (16), uses TLS 1.0 (03 01), the message length is 36 Bytes (00 24). And here is where I am stuck: what does the ae mean?! At first I thought it might have something to do with SNI or some other TLS extension, but so far no luck there either.
Any help interpreting this would be appreciated.
There is no HandshakeType with a value of 174. The 174 shows up because the TLS connection just finished negotiating a cipher suite, and is now encrypting the record's payload!

Resources