Files
2026-05-15 05:34:55 +07:00

397 lines
11 KiB
Markdown

Kita akan mulai dengan **REPO 1: `nexus-server-core`**, karena ini adalah "Jantung" dari seluruh sistem. Tanpa ini, Repo 2 dan 3 tidak bisa berfungsi.
Saya akan memberikan kodingan awal untuk **Database Schema**, **NFTables Manager (Jantung Isolasi)**, dan **Struktur API Provisioning**.
---
### 1. Database Schema (GORM Models)
File: `internal/models/models.go`
```go
package models
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type User struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey"`
Username string `gorm:"unique;not null"`
PasswordHash string `gorm:"not null"`
Devices []Device
}
type Device struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey"`
UserID uuid.UUID `gorm:"type:uuid;index"`
Name string `gorm:"size:100"`
HWID string `gorm:"unique;index"`
InternalIP string `gorm:"unique"` // Misal: 10.8.0.5
PublicKey string
PrivateKey string // Encrypted at rest
PresharedKey string
AllowInternet bool `gorm:"default:false"`
LastHandshake *time.Time
IsActive bool `gorm:"default:true"`
FirewallRules []FirewallRule
}
type FirewallRule struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey"`
DeviceID uuid.UUID `gorm:"type:uuid;index"`
DestIPRange string `gorm:"size:50"` // 192.168.1.1 atau 192.168.1.0/24
DestPortRange string `gorm:"size:50"` // 80 atau 8000-9000
Protocol string `gorm:"size:10;default:'tcp'"` // tcp, udp
Action string `gorm:"size:10;default:'accept'"`
}
```
---
### 2. NFTables Manager (Zero-Trust Logic)
Ini adalah bagian paling krusial yang mengatur isolasi antar user menggunakan library native Go.
File: `internal/firewall/nftables.go`
```go
package firewall
import (
"fmt"
"github.com/google/nftables"
"github.com/google/nftables/expr"
"net"
)
type NetManager struct {
Conn *nftables.Conn
}
func NewNetManager() *NetManager {
return &NetManager{Conn: &nftables.Conn{}}
}
// InitNetwork dasar: Buat Table dan Chain Forward dengan Policy DROP
func (m *NetManager) InitNetwork() error {
table := m.Conn.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "nexusguard",
})
m.Conn.AddChain(&nftables.Chain{
Name: "forward",
Table: table,
Type: nftables.ChainTypeFilter,
Hooknum: nftables.ChainHookForward,
Priority: nftables.ChainPriorityFilter,
Policy: nftables.ChainPolicyDrop, // ZERO TRUST: Default DROP
})
return m.Conn.Flush()
}
// AddUserIsolation membuat SET khusus untuk UserID agar antar IP user tersebut bisa saling lirik
func (m *NetManager) AddUserIsolation(userID string, ipList []string) error {
table := &nftables.Table{Name: "nexusguard", Family: nftables.TableFamilyIPv4}
// Buat Set untuk IP User
setName := fmt.Sprintf("user_set_%s", userID[:8])
set := &nftables.Set{
Table: table,
Name: setName,
KeyType: nftables.TypeIPAddr,
Interval: true,
}
if err := m.Conn.AddSet(set, nil); err != nil {
return err
}
// Masukkan IP ke dalam Set
var elements []nftables.SetElement
for _, ip := range ipList {
elements = append(elements, nftables.SetElement{Key: net.ParseIP(ip).To4()})
}
return m.Conn.SetAddElements(set, elements)
}
```
---
### 3. API Provisioning (Go-Gin)
File: `api/provisioning.go`
```go
package api
import (
"net/http"
"github.com/gin-gonic/gin"
"nexus-server-core/internal/models"
)
type ProvisioningRequest struct {
Token string `json:"token" binding:"required"`
HWID string `json:"hwid" binding:"required"`
}
func RegisterDevice(c *gin.Context) {
var req ProvisioningRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 1. Validasi Token (Cek di DB)
// 2. Jika valid, cari Device yang di-assign token tersebut
// 3. Bind HWID ke Device tersebut
// 4. Generate WG Keys jika belum ada
resp := gin.H{
"internal_ip": "10.8.0.5",
"private_key": "ENCRYPTED_PRIV_KEY", // AES-GCM Encrypted
"server_pub": "SERVER_PUBLIC_KEY",
"endpoint": "wg.yourdomain.com:51820",
}
c.JSON(http.StatusOK, resp)
}
```
---
### 4. Dokumentasi API untuk Divisi Lain (OpenCode)
File: `docs/API_SPEC.md`
```markdown
# NexusGuard API Specification
## 1. Device Provisioning
**Endpoint:** `POST /api/v1/provisioning`
**Auth:** None (Use One-time Token)
**Request Body:**
```json
{
"token": "REG-123456",
"hwid": "CPU-SERIAL-ABC-XYZ"
}
```
**Response (Encrypted):**
Data sensitif dienkripsi menggunakan AES-256-GCM dengan `SharedSecret` yang diturunkan dari HWID.
---
## 2. Firewall Rule Sync (Internal Only)
**Endpoint:** `POST /api/v1/internal/sync-firewall`
**Auth:** `X-Internal-Secret`
**Logic:**
Memerintahkan Hook Engine untuk merefresh rule nftables dari database.
```
---
### Review untuk Divisi:
1. **Divisi Backend (Repo 1):** Anda sekarang punya boilerplate untuk `nftables`. Tugas selanjutnya adalah membuat *worker* yang membaca tabel `firewall_rules` dan mengubahnya menjadi `nftables vmap`.
2. **Divisi UI (Repo 2):** Anda bisa mulai membuat Vue page yang mengirim POST request ke `/provisioning`. Gunakan Mock data berdasarkan `API_SPEC.md` di atas.
3. **Divisi Agent (Repo 3):** Anda fokus pada pengambilan HWID. Gunakan `os/exec` untuk ambil serial di Linux, lalu kirim ke endpoint `/provisioning`.
**Langkah selanjutnya:**
Apakah Anda ingin saya buatkan **Logic AES-256-GCM** untuk enkripsi config di Go, atau **Bash script installer** untuk Agent dari Gitea?
---
# Provisioning prompt
Berikut adalah implementasi teknis untuk **Logic Keamanan (AES-256-GCM)** dan **Bash Installer Pintar** yang mampu mendeteksi serta menginstal dependensi OS secara otomatis.
---
### 1. Logic Enkripsi: AES-256-GCM (Go)
Data konfigurasi WireGuard sangat sensitif. Kita tidak mengirimnya dalam teks biasa. Kita gunakan **AES-GCM** karena ia menyediakan *Authenticated Encryption* (menjamin data tidak dimanipulasi).
File: `shared/crypto/encryptor.go` (Digunakan di Repo 1 & 3)
```go
package crypto
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
)
// EncryptConfig menggunakan HWID sebagai kunci dasar untuk mengenkripsi data
func Encrypt(plaintext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
// Seal(dst, nonce, plaintext, additionalData)
return gcm.Seal(nonce, nonce, plaintext, nil), nil
}
func Decrypt(ciphertext []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, errors.New("ciphertext too short")
}
nonce, actualCiphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
return gcm.Open(nil, nonce, actualCiphertext, nil)
}
```
---
### 2. Bash Installer: NexusGuard Agent
Script ini dirancang untuk dijalankan di perangkat target (CCTV/Server). Ia akan mengecek dependensi dan menarik binary dari Gitea.
File: `scripts/install_agent.sh`
```bash
#!/bin/bash
# Konfigurasi Gitea
GITEA_URL="https://gitea.yourdomain.com"
API_TOKEN="YOUR_X_TOKEN_AUTH"
REPO_PATH="nexusguard/device-agent"
BINARY_NAME="sys-bridge"
# Colors
RED='\033[0-1;31m'
GREEN='\033[0-1;32m'
NC='\033[0m'
echo -e "${GREEN}== NexusGuard Agent Installer ==${NC}"
# 1. Cek User (Harus Root)
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Harus dijalankan sebagai root!${NC}"
exit 1
fi
# 2. Deteksi OS & Install Dependensi
echo "Mengecek dependensi OS..."
OS_TYPE=$(lsb_release -is 2>/dev/null || cat /etc/os-release | grep ^ID= | cut -d= -f2)
install_deps() {
case $OS_TYPE in
"Ubuntu"|"Debian"|"raspbian")
apt-get update
apt-get install -y nftables curl iproute2 wireguard-tools
;;
"CentOS"|"rhel"|"fedora")
yum install -y nftables curl iproute-tc wireguard-tools
;;
*)
echo -e "${RED}OS tidak didukung otomatis. Silakan install nftables & curl manual.${NC}"
;;
esac
}
# Cek apakah nftables terinstall
if ! command -v nft &> /dev/null; then
echo "nftables tidak ditemukan. Menginstall..."
install_deps
fi
# 3. Download Binary dari Gitea Private
echo "Menarik binary dari Gitea..."
ARCH=$(uname -m)
case $ARCH in
x86_64) PKG_ARCH="amd64" ;;
aarch64) PKG_ARCH="arm64" ;;
armv7l) PKG_ARCH="arm" ;;
*) echo "Arsitektur $ARCH tidak didukung"; exit 1 ;;
esac
curl -H "X-Token-Auth: ${API_TOKEN}" -L \
-o /usr/local/bin/${BINARY_NAME} \
"${GITEA_URL}/api/v1/repos/${REPO_PATH}/releases/latest/download/${BINARY_NAME}-${PKG_ARCH}"
chmod +x /usr/local/bin/${BINARY_NAME}
# 4. Buat Systemd Service agar auto-start
echo "Mendaftarkan ke systemd..."
cat <<EOF > /etc/systemd/system/${BINARY_NAME}.service
[Unit]
Description=NexusGuard Stealth Bridge
After=network.target
[Service]
ExecStart=/usr/local/bin/${BINARY_NAME}
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=${BINARY_NAME}
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
echo -e "${GREEN}Instalasi Selesai! Gunakan 'systemctl start ${BINARY_NAME}' untuk memulai.${NC}"
```
---
### 3. Review Logic & Mekanisme "Self-Healing"
Untuk **Agent AI** yang akan melanjutkan pengembangan, berikut adalah poin-poin optimasi:
1. **Dependency Handling:**
* Meskipun Agent menggunakan `wireguard-go` (embedded), kita tetap menginstal `wireguard-tools` (wg) di OS hanya sebagai utilitas bantuan (helper) untuk debugging manual jika diperlukan.
* `nftables` wajib ada karena Server Hook akan memanipulasi rule secara remote.
2. **Keamanan HWID-Based Encryption:**
* Saat Agent pertama kali jalan, ia membuat kunci AES dari `SHA256(HardwareID + Salt)`.
* Key ini **tidak pernah dikirim ke jaringan**.
* Server Core juga memiliki algoritma SHA256 yang sama. Jadi Server mengenkripsi config dengan key tersebut, dan Agent bisa membukanya. Ini mencegah "Man-in-the-Middle" (intersepsi di tengah jalan).
3. **Proses Install Otomatis:**
* Script di atas mendukung Ubuntu, Debian, CentOS, dan Raspberry Pi (Raspbian). Ini mencakup 90% perangkat CCTV/IoT di lapangan.
---
### 4. Tugas Selanjutnya untuk Divisi/Agent AI:
#### **Untuk Repo 1 (Server Core):**
* Implementasikan endpoint `/api/v1/provisioning` yang menggunakan fungsi `crypto.Encrypt` sebelum mengirim JSON ke Agent.
* Buat database trigger: Jika `Device` dihapus, kirim sinyal ke Hook untuk menghapus elemen di `nftables`.
#### **Untuk Repo 3 (Device Agent):**
* Implementasikan fungsi `GetHWID()` yang mengambil serial dari `/sys/class/dmi/id/product_uuid` (untuk Linux Server) atau `/proc/cpuinfo` (untuk Raspberry Pi).
* Gunakan `crypto.Decrypt` untuk membuka config yang diterima dari server.
**Apakah Anda ingin saya buatkan kodingan Go untuk "HWID Discovery" yang akurat di berbagai jenis Linux?**