Skip to content

Instantly share code, notes, and snippets.

@rafkatg
Created February 24, 2024 13:56
Show Gist options
  • Select an option

  • Save rafkatg/c8b5d233d003fae9c17aa0a4a6df92d9 to your computer and use it in GitHub Desktop.

Select an option

Save rafkatg/c8b5d233d003fae9c17aa0a4a6df92d9 to your computer and use it in GitHub Desktop.

Revisions

  1. rafkatg created this gist Feb 24, 2024.
    90 changes: 90 additions & 0 deletions server.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    package main

    import (
    "log"
    "net"
    "sync"
    "time"
    )

    const (
    maxRequestsPerIP = 100 // Limit requests from each IP address
    maxConnectionsPerIP = 5 // Limit connections from each IP address
    )

    type request struct {
    ip net.IP
    request chan *net.UDPConn
    }

    type server struct {
    requests map[string]*request
    requestMutex sync.Mutex
    connections map[string]int
    }

    func NewServer() *server {
    return &server{
    requests: make(map[string]*request),
    requestMutex: sync.Mutex{},
    connections: make(map[string]int),
    }
    }

    func (s *server) ServeUDP(conn *net.UDPConn, addr net.Addr) error {
    s.requestMutex.Lock()
    defer s.requestMutex.Unlock()

    ip := addr.IP
    if _, exists := s.connections[ip]; exists {
    s.connections[ip]++
    if s.connections[ip] > maxConnectionsPerIP {
    log.Printf("Connection limit exceeded for IP: %s", ip)
    conn.Close()
    return nil
    }
    } else {
    s.connections[ip] = 1
    }

    s.requestMutex.Unlock()

    request := &request{
    ip: ip,
    request: make(chan *net.UDPConn, maxRequestsPerIP)),
    }
    s.requests[ip] = request

    go s.handleRequest(request)

    return nil
    }

    func (s *server) handleRequest(request *request) {
    defer close(request.request)

    for i := 0; i < maxRequestsPerIP; i++ {
    conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: 1080, IP: request.ip}})

    if err != nil {
    log.Printf("Error while listening for UDP connection: %v", err)
    continue
    }

    request.request <- conn
    }
    }

    func main() {
    server := NewServer()
    listener, err := net.Listen("tcp", ":8080"))
    if err != nil {
    log.Fatal(err)
    }
    defer listener.Close()

    for {
    conn, _ := listener.Accept()
    go server.Serve(conn, conn.RemoteAddr()))
    }
    }