Исправлена распаковка ws с контентом в пакете с хендшейком

This commit is contained in:
sshkurov
2021-06-09 00:08:41 +03:00
parent f041f3b7b9
commit 1219670d51
2 changed files with 54 additions and 12 deletions

View File

@@ -2,6 +2,7 @@ package ru.serega6531.packmate.service.optimization;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.java_websocket.drafts.Draft_6455; import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.exceptions.InvalidDataException; import org.java_websocket.exceptions.InvalidDataException;
import org.java_websocket.exceptions.InvalidHandshakeException; import org.java_websocket.exceptions.InvalidHandshakeException;
@@ -11,25 +12,27 @@ import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.HandshakeImpl1Client; import org.java_websocket.handshake.HandshakeImpl1Client;
import org.java_websocket.handshake.HandshakeImpl1Server; import org.java_websocket.handshake.HandshakeImpl1Server;
import ru.serega6531.packmate.model.Packet; import ru.serega6531.packmate.model.Packet;
import ru.serega6531.packmate.utils.BytesUtils;
import ru.serega6531.packmate.utils.PacketUtils; import ru.serega6531.packmate.utils.PacketUtils;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j @Slf4j
public class WebSocketsParser { public class WebSocketsParser {
private static final java.util.regex.Pattern WEBSOCKET_KEY_PATTERN = private static final java.util.regex.Pattern WEBSOCKET_KEY_PATTERN =
java.util.regex.Pattern.compile("Sec-WebSocket-Key: (.+)\\r\\n"); Pattern.compile("Sec-WebSocket-Key: (.+)\\r\\n");
private static final java.util.regex.Pattern WEBSOCKET_EXTENSIONS_PATTERN = private static final java.util.regex.Pattern WEBSOCKET_EXTENSIONS_PATTERN =
java.util.regex.Pattern.compile("Sec-WebSocket-Extensions?: (.+)\\r\\n"); Pattern.compile("Sec-WebSocket-Extensions?: (.+)\\r\\n");
private static final java.util.regex.Pattern WEBSOCKET_VERSION_PATTERN = private static final java.util.regex.Pattern WEBSOCKET_VERSION_PATTERN =
java.util.regex.Pattern.compile("Sec-WebSocket-Version: (\\d+)\\r\\n"); Pattern.compile("Sec-WebSocket-Version: (\\d+)\\r\\n");
private static final java.util.regex.Pattern WEBSOCKET_ACCEPT_PATTERN = private static final java.util.regex.Pattern WEBSOCKET_ACCEPT_PATTERN =
java.util.regex.Pattern.compile("Sec-WebSocket-Accept: (.+)\\r\\n"); Pattern.compile("Sec-WebSocket-Accept: (.+)\\r\\n");
private static final String WEBSOCKET_UPGRADE_HEADER = "upgrade: websocket\r\n"; private static final String WEBSOCKET_UPGRADE_HEADER = "upgrade: websocket\r\n";
private static final String WEBSOCKET_CONNECTION_HEADER = "connection: upgrade\r\n"; private static final String WEBSOCKET_CONNECTION_HEADER = "connection: upgrade\r\n";
@@ -57,7 +60,20 @@ public class WebSocketsParser {
int httpEnd = -1; int httpEnd = -1;
for (int i = clientHandshakePackets.size(); i < packets.size(); i++) { for (int i = clientHandshakePackets.size(); i < packets.size(); i++) {
if (packets.get(i).getContentString().endsWith("\r\n\r\n")) { Packet packet = packets.get(i);
byte[] content = packet.getContent();
if (BytesUtils.startsWith(content, "HTTP/1.1 101 Switching Protocols".getBytes())) {
int endPos = BytesUtils.indexOf(content, "\r\n\r\n".getBytes()) + "\r\n\r\n".length();
if (endPos != content.length) {
byte[] handshakePart = ArrayUtils.subarray(content, 0, endPos);
byte[] payloadPart = ArrayUtils.subarray(content, endPos, content.length);
Packet handshakePacket = mimicPacket(packet, handshakePart, false);
Packet payloadPacket = mimicPacket(packet, payloadPart, true);
packets.add(i, handshakePacket);
packets.set(i + 1, payloadPacket);
}
httpEnd = i + 1; httpEnd = i + 1;
break; break;
} }
@@ -94,7 +110,7 @@ public class WebSocketsParser {
httpEnd, httpEnd,
packets.size()); packets.size());
if(wsPackets.isEmpty()) { if (wsPackets.isEmpty()) {
return; return;
} }
@@ -103,6 +119,18 @@ public class WebSocketsParser {
parse(wsPackets, handshakes, draft); parse(wsPackets, handshakes, draft);
} }
private Packet mimicPacket(Packet packet, byte[] content, boolean ws) {
return Packet.builder()
.content(content)
.incoming(packet.isIncoming())
.timestamp(packet.getTimestamp())
.ttl(packet.getTtl())
.ungzipped(packet.isUngzipped())
.webSocketParsed(ws)
.tlsDecrypted(packet.isTlsDecrypted())
.build();
}
private void parse(final List<Packet> wsPackets, final List<Packet> handshakes, Draft_6455 draft) { private void parse(final List<Packet> wsPackets, final List<Packet> handshakes, Draft_6455 draft) {
List<List<Packet>> sides = PacketUtils.sliceToSides(wsPackets); List<List<Packet>> sides = PacketUtils.sliceToSides(wsPackets);
parsedPackets = new ArrayList<>(handshakes); parsedPackets = new ArrayList<>(handshakes);
@@ -124,7 +152,7 @@ public class WebSocketsParser {
} }
for (Framedata frame : frames) { for (Framedata frame : frames) {
if(frame instanceof DataFrame) { if (frame instanceof DataFrame) {
parsedPackets.add(Packet.builder() parsedPackets.add(Packet.builder()
.content(frame.getPayloadData().array()) .content(frame.getPayloadData().array())
.incoming(lastPacket.isIncoming()) .incoming(lastPacket.isIncoming())
@@ -190,7 +218,7 @@ public class WebSocketsParser {
clientHandshakeImpl.put("Sec-WebSocket-Version", version); clientHandshakeImpl.put("Sec-WebSocket-Version", version);
clientHandshakeImpl.put("Sec-WebSocket-Key", key); clientHandshakeImpl.put("Sec-WebSocket-Key", key);
if(extensions != null) { if (extensions != null) {
clientHandshakeImpl.put("Sec-WebSocket-Extensions", extensions); clientHandshakeImpl.put("Sec-WebSocket-Extensions", extensions);
} }

View File

@@ -11,10 +11,10 @@ import static org.pcap4j.util.ByteArrays.BYTE_SIZE_IN_BITS;
@UtilityClass @UtilityClass
public class BytesUtils { public class BytesUtils {
/** public int indexOf(byte[] array, byte[] target) {
* @param array где ищем return indexOf(array, target, 0, array.length);
* @param target что ищем }
*/
public int indexOf(byte[] array, byte[] target, int start, int end) { public int indexOf(byte[] array, byte[] target, int start, int end) {
if (target.length == 0) { if (target.length == 0) {
return 0; return 0;
@@ -32,6 +32,20 @@ public class BytesUtils {
return -1; return -1;
} }
public boolean startsWith(byte[] array, byte[] prefix) {
if (prefix.length > array.length) {
return false;
}
for (int i = 0; i < prefix.length; i++) {
if (array[i] != prefix[i]) {
return false;
}
}
return true;
}
/** /**
* @param array где ищем * @param array где ищем
* @param target что ищем * @param target что ищем