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

11 KiB

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

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

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

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

# 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

#!/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?