Parcourir la source

Merge pull request #3 from Lanius-collaris/packetman-fix

packetman: fix "TCP-dataoffset" tranformation and "TCP-checksum" tranformation
Rod Hynes il y a 2 ans
Parent
commit
58fb8d025c
2 fichiers modifiés avec 27 ajouts et 23 suppressions
  1. 9 0
      contributors/Lanius-collaris.md
  2. 18 23
      psiphon/common/packetman/packetman.go

+ 9 - 0
contributors/Lanius-collaris.md

@@ -0,0 +1,9 @@
+2023-12-09
+
+I hereby agree to the terms of the "Psiphon Individual Contributor License Agreement", with sha256 checksum 5c61081564a8afbe1bb91b48c291f93a9ead7ae92b5329d05a19bcc5ccec4b4b.
+
+I furthermore declare that I am authorized and able to make this agreement and sign this declaration.
+
+Signed,
+
+Lanius Collaris https://github.com/Lanius-collaris

+ 18 - 23
psiphon/common/packetman/packetman.go

@@ -134,14 +134,14 @@ type Config struct {
 // "TCP-flags random|<flags>"
 // flags: FSRPAUECN
 //
-// "TCP-<field> random|<base64>"
+// "TCP-<field> random|<hex>"
 // field: srcport, dstport, seq, ack, dataoffset, window, checksum, urgent
 //
-// "TCP-option-<option> random|omit|<base64>"
+// "TCP-option-<option> random|omit|<hex>"
 // option: eol, nop, mss, windowscale, sackpermitted, sack, timestamps,
 // altchecksum, altchecksumdata, md5header, usertimeout
 //
-// "TCP-payload random|<base64>"
+// "TCP-payload random|<hex>"
 //
 // For example, this Geneva strategy:
 //   [TCP:flags:SA]-duplicate(tamper{TCP:flags:replace:R},tamper{TCP:flags:replace:S})-| \/
@@ -222,10 +222,17 @@ 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() {
+			if t, ok := transform.(*transformationTCPField); ok && t.fieldName == tcpFieldDataOffset {
+				fixLengths = false
+				setCalculatedField = true
+			}
+			if t, ok := transform.(*transformationTCPField); ok && t.fieldName == tcpFieldChecksum {
+				computeChecksums = false
 				setCalculatedField = true
 			}
 		}
@@ -238,6 +245,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 +266,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 +279,11 @@ 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
 }
 
 const (
@@ -388,10 +399,6 @@ func (t *transformationTCPFlags) apply(tcp *layers.TCP, _ *gopacket.Payload) {
 	tcp.NS = strings.Index(t.flags, "N") != -1
 }
 
-func (t *transformationTCPFlags) setsCalculatedField() bool {
-	return false
-}
-
 type transformationTCPField struct {
 	fieldName          string
 	transformationType int
@@ -492,10 +499,6 @@ func (t *transformationTCPField) apply(tcp *layers.TCP, _ *gopacket.Payload) {
 	}
 }
 
-func (t *transformationTCPField) setsCalculatedField() bool {
-	return t.fieldName == tcpFieldDataOffset || t.fieldName == tcpFieldChecksum
-}
-
 type transformationTCPOption struct {
 	optionName         string
 	transformationType int
@@ -706,10 +709,6 @@ func (t *transformationTCPOption) apply(tcp *layers.TCP, _ *gopacket.Payload) {
 	tcp.Options = options
 }
 
-func (t *transformationTCPOption) setsCalculatedField() bool {
-	return false
-}
-
 type transformationTCPPayload struct {
 	transformationType int
 	value              []byte
@@ -763,10 +762,6 @@ func (t *transformationTCPPayload) apply(tcp *layers.TCP, payload *gopacket.Payl
 	}
 }
 
-func (t *transformationTCPPayload) setsCalculatedField() bool {
-	return false
-}
-
 func stripEOLOption(packet gopacket.Packet) {
 
 	// gopacket.NewPacket appears to decode padding (0s) as an explicit EOL