mvp
This commit is contained in:
parent
3f83c9d9a1
commit
890a3f527b
|
@ -1,3 +1,6 @@
|
|||
.idea
|
||||
config.yml
|
||||
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
@ -159,4 +162,3 @@ cython_debug/
|
|||
# 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.
|
||||
#.idea/
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# 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