mvp
This commit is contained in:
parent
3f83c9d9a1
commit
890a3f527b
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
chacha_key: example123
|
||||||
|
|
||||||
|
destinations:
|
||||||
|
5170:
|
||||||
|
address: 192.168.1.200
|
||||||
|
port: 8080
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Key: $(openssl rand -hex 32)"
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
|
@ -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=
|
|
@ -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 {}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
```shell
|
||||||
|
pip install pycryptodome
|
||||||
|
```
|
|
@ -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)
|
Loading…
Reference in New Issue