Просмотр исходного кода

packetman: fix "TCP-dataoffset" tranformation and "TCP-checksum" tranformation

Lanius-collaris 2 лет назад
Родитель
Сommit
cc93afe3fb
1 измененных файлов с 49 добавлено и 2 удалено
  1. 49 2
      psiphon/common/packetman/packetman.go

+ 49 - 2
psiphon/common/packetman/packetman.go

@@ -222,12 +222,20 @@ func (spec *compiledSpec) apply(interceptedPacket gopacket.Packet) ([][]byte, er
 		transformedTCP := *interceptedTCP
 		var payload gopacket.Payload
 		setCalculatedField := false
+		fixLengths := true
+		computeChecksums := true
 
 		for _, transform := range packetTransformations {
 			transform.apply(&transformedTCP, &payload)
 			if transform.setsCalculatedField() {
 				setCalculatedField = true
 			}
+			if transform.isDataOffset() {
+				fixLengths = false
+			}
+			if transform.isChecksum() {
+				computeChecksums = false
+			}
 		}
 
 		err := transformedTCP.SetNetworkLayerForChecksum(networkLayer)
@@ -238,6 +246,10 @@ func (spec *compiledSpec) apply(interceptedPacket gopacket.Packet) ([][]byte, er
 		buffer := gopacket.NewSerializeBuffer()
 		options := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
 
+		//warning: first SerializeLayers call may modify transformedTCP, we must copy the TCP DataOffset and Checksum
+		tmpDataOffset := transformedTCP.DataOffset
+		tmpChecksum := transformedTCP.Checksum
+
 		gopacket.SerializeLayers(
 			buffer,
 			options,
@@ -255,10 +267,12 @@ func (spec *compiledSpec) apply(interceptedPacket gopacket.Packet) ([][]byte, er
 		// from the first round.
 
 		if setCalculatedField {
+			transformedTCP.DataOffset = tmpDataOffset
+			transformedTCP.Checksum = tmpChecksum
 			buffer.Clear()
 			gopacket.SerializeLayers(
 				buffer,
-				gopacket.SerializeOptions{},
+				gopacket.SerializeOptions{FixLengths: fixLengths, ComputeChecksums: computeChecksums},
 				serializableNetworkLayer,
 				&transformedTCP,
 				payload)
@@ -266,13 +280,14 @@ func (spec *compiledSpec) apply(interceptedPacket gopacket.Packet) ([][]byte, er
 
 		packets[i] = buffer.Bytes()
 	}
-
 	return packets, nil
 }
 
 type transformation interface {
 	apply(tcp *layers.TCP, payload *gopacket.Payload)
 	setsCalculatedField() bool
+	isDataOffset() bool
+	isChecksum() bool
 }
 
 const (
@@ -392,6 +407,14 @@ func (t *transformationTCPFlags) setsCalculatedField() bool {
 	return false
 }
 
+func (t *transformationTCPFlags) isDataOffset() bool {
+	return false
+}
+
+func (t *transformationTCPFlags) isChecksum() bool {
+	return false
+}
+
 type transformationTCPField struct {
 	fieldName          string
 	transformationType int
@@ -496,6 +519,14 @@ func (t *transformationTCPField) setsCalculatedField() bool {
 	return t.fieldName == tcpFieldDataOffset || t.fieldName == tcpFieldChecksum
 }
 
+func (t *transformationTCPField) isDataOffset() bool {
+	return t.fieldName == tcpFieldDataOffset
+}
+
+func (t *transformationTCPField) isChecksum() bool {
+	return t.fieldName == tcpFieldChecksum
+}
+
 type transformationTCPOption struct {
 	optionName         string
 	transformationType int
@@ -710,6 +741,14 @@ func (t *transformationTCPOption) setsCalculatedField() bool {
 	return false
 }
 
+func (t *transformationTCPOption) isDataOffset() bool {
+	return false
+}
+
+func (t *transformationTCPOption) isChecksum() bool {
+	return false
+}
+
 type transformationTCPPayload struct {
 	transformationType int
 	value              []byte
@@ -767,6 +806,14 @@ func (t *transformationTCPPayload) setsCalculatedField() bool {
 	return false
 }
 
+func (t *transformationTCPPayload) isDataOffset() bool {
+	return false
+}
+
+func (t *transformationTCPPayload) isChecksum() bool {
+	return false
+}
+
 func stripEOLOption(packet gopacket.Packet) {
 
 	// gopacket.NewPacket appears to decode padding (0s) as an explicit EOL