This commit is contained in:
Cyberes 2024-06-27 17:16:47 -06:00
parent 3f83c9d9a1
commit 890a3f527b
10 changed files with 205 additions and 2 deletions

4
.gitignore vendored
View File

@ -1,3 +1,6 @@
.idea
config.yml
# ---> Python # ---> Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
@ -159,4 +162,3 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/

View File

@ -1,3 +1,5 @@
# freematics-traccar-encrypted # freematics-traccar-encrypted
A proxy to encrypt the Traccar Freematics protocol. _A proxy to encrypt the Traccar Freematics protocol._
https://github.com/rfhigler/Freematics/commit/25cf781ca9fecc3e3082348ce9d28e4d69ff7764

6
config.sample.yml Normal file
View File

@ -0,0 +1,6 @@
chacha_key: example123
destinations:
5170:
address: 192.168.1.200
port: 8080

4
generate-key.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
echo "Key: $(openssl rand -hex 32)"

View File

@ -0,0 +1,24 @@
package encryption
import (
"errors"
"golang.org/x/crypto/chacha20poly1305"
)
func Decrypt(key, ciphertextMsg []byte) ([]byte, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
nonceSize := aead.NonceSize()
tagSize := aead.Overhead()
if len(ciphertextMsg) < nonceSize+tagSize {
return nil, errors.New("ciphertext too short")
}
// Split nonce and ciphertext.
nonce, ciphertext, tag := ciphertextMsg[:nonceSize], ciphertextMsg[nonceSize:len(ciphertextMsg)-tagSize], ciphertextMsg[len(ciphertextMsg)-tagSize:]
return aead.Open(nil, nonce, append(ciphertext, tag...), nil)
}

10
server/go.mod Normal file
View File

@ -0,0 +1,10 @@
module server
go 1.22.2
require (
golang.org/x/crypto v0.24.0
gopkg.in/yaml.v2 v2.4.0
)
require golang.org/x/sys v0.21.0 // indirect

8
server/go.sum Normal file
View File

@ -0,0 +1,8 @@
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

116
server/server.go Normal file
View File

@ -0,0 +1,116 @@
package main
import (
"encoding/hex"
"flag"
"fmt"
"gopkg.in/yaml.v2"
"net"
"os"
"server/encryption"
)
type Config struct {
Destinations map[string]Destination `yaml:"destinations"`
ChachaKey string `yaml:"chacha_key"`
}
type Destination struct {
Address string `yaml:"address"`
Port int `yaml:"port"`
}
func main() {
configFile := flag.String("config", "", "Path to the configuration file")
flag.Parse()
if *configFile == "" {
fmt.Println("Please provide a configuration file")
os.Exit(1)
}
data, err := os.ReadFile(*configFile)
if err != nil {
fmt.Println("Error reading the configuration file:", err)
os.Exit(1)
}
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
fmt.Println("Error parsing the configuration file:", err)
os.Exit(1)
}
// Validate chacha key
if len(config.ChachaKey) != 64 {
fmt.Println("Invalid chacha_key. Should be 64 characters long")
os.Exit(1)
}
// Validate destinations
for port, dest := range config.Destinations {
if dest.Address == "" || dest.Port == 0 {
fmt.Printf("Invalid destination for port %s\n", port)
os.Exit(1)
}
}
key, _ := hex.DecodeString(config.ChachaKey)
for port, dest := range config.Destinations {
go func(port string, dest Destination) {
addr, err := net.ResolveUDPAddr("udp", ":"+port)
if err != nil {
fmt.Println("Error resolving address:", err)
return
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
fmt.Println("Error listening on UDP:", err)
return
}
defer conn.Close()
// Address to forward the decrypted messages
forwardAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", dest.Address, dest.Port))
if err != nil {
fmt.Println("Error resolving forward address:", err)
return
}
forwardConn, err := net.DialUDP("udp", nil, forwardAddr)
if err != nil {
fmt.Println("Error dialing to forward address:", err)
return
}
defer forwardConn.Close()
for {
buf := make([]byte, 1500) // 1500 is the standard internet MTU
n, addr, err := conn.ReadFromUDP(buf)
if err != nil {
fmt.Println("Error reading from UDP:", err)
return
}
plaintext, err := encryption.Decrypt(key, buf[:n]) // Use only the part of the buffer that has data
if err != nil {
fmt.Println("Error decrypting message:", err)
return
}
fmt.Printf("%s -- %s\n", addr.IP, string(plaintext))
// Forward the decrypted message
_, err = forwardConn.Write(plaintext)
if err != nil {
fmt.Println("Error forwarding message:", err)
return
}
}
}(port, dest)
}
select {}
}

3
test/README.md Normal file
View File

@ -0,0 +1,3 @@
```shell
pip install pycryptodome
```

28
test/test.py Normal file
View File

@ -0,0 +1,28 @@
import socket
import time
from Crypto.Cipher import ChaCha20_Poly1305
# The server's address and port
server_address = ('localhost', 5170)
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# The message to be sent
message = ('Hello, Server! ' + str(time.time())).encode()
# The key and nonce
key = bytes.fromhex('example123')
# Encrypt the message
cipher = ChaCha20_Poly1305.new(key=key)
ciphertext, tag = cipher.encrypt_and_digest(message)
# Send the encrypted message to the server
sock.sendto(cipher.nonce + ciphertext + tag, server_address)
sock.close()
cipher = ChaCha20_Poly1305.new(key=key, nonce=cipher.nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
print(plaintext)