Compare commits

...

22 Commits
icmp2 ... 1.8.1

Author SHA1 Message Date
Owen
6c05d76c88 Merge branch 'main' into dev 2025-12-24 15:18:11 -05:00
Owen
a701add824 Reuse http client for each target
Fixes #220
2025-12-24 10:58:46 -05:00
Owen
d754cea397 Dont run on v tags 2025-12-23 17:54:31 -05:00
Owen
31d52ad3ff Quiet up HandleIncomingPacket 2025-12-23 10:29:15 -05:00
Owen
e1ee4dc8f2 Fix latest tag 2025-12-22 21:32:47 -05:00
Varun Narravula
f9b6f36b4f ci: update nix go vendor hash if needed for dependabot PRs 2025-12-22 19:43:48 -05:00
Varun Narravula
0e961761b8 chore: add direnv and nix result dirs to gitignore 2025-12-22 19:43:48 -05:00
Varun Narravula
baf1b9b972 ci: build nix package when go.mod is changed 2025-12-22 19:43:48 -05:00
Varun Narravula
f078136b5a fix(nix): disable tests, set meta.mainProgram for package 2025-12-22 19:43:48 -05:00
Varun Narravula
ca341a8bb0 chore(nix): sync version number with latest version 2025-12-22 19:43:48 -05:00
Owen
80ae03997a Merge branch 'dev' 2025-12-22 16:15:41 -05:00
Owen
5c94789d9a Quiet up logs 2025-12-22 14:31:44 -05:00
Owen
6c65cc8e5e Fix makefile cicd binaries 2025-12-21 21:34:56 -05:00
Owen
a21a8e90fa Add back release and binaries 2025-12-21 21:01:04 -05:00
Owen
3d5335f2cb Add back release and binaries 2025-12-21 21:00:45 -05:00
Owen Schwartz
94788edce3 Merge pull request #214 from fosrl/dev
1.8.0-rc.0
2025-12-21 20:59:32 -05:00
Owen
2bbe037544 Merge branch 'main' into dev 2025-12-21 20:57:45 -05:00
Owen
9b015e9f7c Tie siteIds to exit node 2025-12-19 10:54:21 -05:00
Owen
3305f711b9 Prevent sigsegv with bad address
Fixes #210
Fixes #201
2025-12-18 10:29:37 -05:00
Owen
ff7fe1275b Take 21820 from config 2025-12-16 18:35:25 -05:00
Owen
1cbf41e094 Take 21820 from config 2025-12-16 18:33:05 -05:00
Owen Schwartz
9bc35433ef Merge pull request #208 from fosrl/icmp2
Support ICMP test requests for clients
2025-12-16 17:19:22 -05:00
14 changed files with 237 additions and 72 deletions

View File

@@ -11,7 +11,9 @@ permissions:
on:
push:
tags:
- "*"
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+"
workflow_dispatch:
inputs:
version:
@@ -273,7 +275,7 @@ jobs:
tags: |
type=semver,pattern={{version}},value=${{ env.TAG }}
type=semver,pattern={{major}}.{{minor}},value=${{ env.TAG }},enable=${{ env.PUBLISH_MINOR == 'true' && env.IS_RC != 'true' }}
type=raw,value=latest,enable=${{ env.PUBLISH_LATEST == 'true' && env.IS_RC != 'true' }}
type=raw,value=latest,enable=${{ env.IS_RC != 'true' }}
flavor: |
latest=false
labels: |
@@ -587,28 +589,28 @@ jobs:
# sarif_file: trivy-ghcr.sarif
# category: Image Vulnerability Scan
# - name: Build binaries
# env:
# CGO_ENABLED: "0"
# GOFLAGS: "-trimpath"
# run: |
# set -euo pipefail
# TAG_VAR="${TAG}"
# make go-build-release tag=$TAG_VAR
# shell: bash
- name: Build binaries
env:
CGO_ENABLED: "0"
GOFLAGS: "-trimpath"
run: |
set -euo pipefail
TAG_VAR="${TAG}"
make -j 10 go-build-release tag=$TAG_VAR
shell: bash
# - name: Create GitHub Release
# uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
# with:
# tag_name: ${{ env.TAG }}
# generate_release_notes: true
# prerelease: ${{ env.IS_RC == 'true' }}
# files: |
# bin/*
# fail_on_unmatched_files: true
# draft: true
# body: |
# ## Container Images
# - GHCR: `${{ env.GHCR_REF }}`
# - Docker Hub: `${{ env.DH_REF || 'N/A' }}`
# **Digest:** `${{ steps.build.outputs.digest }}`
- name: Create GitHub Release
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
with:
tag_name: ${{ env.TAG }}
generate_release_notes: true
prerelease: ${{ env.IS_RC == 'true' }}
files: |
bin/*
fail_on_unmatched_files: true
draft: true
body: |
## Container Images
- GHCR: `${{ env.GHCR_REF }}`
- Docker Hub: `${{ env.DH_REF || 'N/A' }}`
**Digest:** `${{ steps.build.outputs.digest }}`

23
.github/workflows/nix-build.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Build Nix package
on:
workflow_dispatch:
pull_request:
paths:
- go.mod
- go.sum
jobs:
nix-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Build flake package
run: |
nix build .#pangolin-newt -L

View File

@@ -0,0 +1,48 @@
name: Update Nix Package Hash On Dependabot PRs
on:
pull_request:
types: [opened, synchronize]
branches:
- main
jobs:
nix-update:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Run nix-update
run: |
nix run nixpkgs#nix-update -- --flake pangolin-newt --no-src --version skip
- name: Check for changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Commit and push changes
if: steps.changes.outputs.changed == 'true'
run: |
git config user.name "dependabot[bot]"
git config user.email "dependabot[bot]@users.noreply.github.com"
git add .
git commit -m "chore(nix): fix hash for updated go dependencies"
git push

4
.gitignore vendored
View File

@@ -5,4 +5,6 @@ nohup.out
*.iml
certs/
newt_arm64
key
key
/.direnv/
/result*

View File

@@ -27,6 +27,18 @@ docker-build-release:
go-build-release-darwin-amd64 go-build-release-windows-amd64 \
go-build-release-freebsd-amd64 go-build-release-freebsd-arm64
go-build-release: \
go-build-release-linux-arm64 \
go-build-release-linux-arm32-v7 \
go-build-release-linux-arm32-v6 \
go-build-release-linux-amd64 \
go-build-release-linux-riscv64 \
go-build-release-darwin-arm64 \
go-build-release-darwin-amd64 \
go-build-release-windows-amd64 \
go-build-release-freebsd-amd64 \
go-build-release-freebsd-arm64
go-build-release-linux-arm64:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/newt_linux_arm64

View File

@@ -24,7 +24,7 @@ func setupClients(client *websocket.Client) {
host = strings.TrimSuffix(host, "/")
logger.Info("Setting up clients with netstack2...")
logger.Debug("Setting up clients with netstack2...")
// if useNativeInterface is true make sure we have permission to use native interface
if useNativeInterface {
@@ -63,7 +63,7 @@ func closeClients() {
}
}
func clientsHandleNewtConnection(publicKey string, endpoint string) {
func clientsHandleNewtConnection(publicKey string, endpoint string, relayPort uint16) {
if !ready {
return
}
@@ -77,7 +77,7 @@ func clientsHandleNewtConnection(publicKey string, endpoint string) {
endpoint = strings.Join(parts[:len(parts)-1], ":")
if wgService != nil {
wgService.StartHolepunch(publicKey, endpoint)
wgService.StartHolepunch(publicKey, endpoint, relayPort)
}
}

View File

@@ -141,7 +141,7 @@ func NewWireGuardService(interfaceName string, port uint16, mtu int, host string
// Add a reference for the hole punch manager (creator already has one reference for WireGuard)
sharedBind.AddRef()
logger.Info("Created shared UDP socket on port %d (refcount: %d)", port, sharedBind.GetRefCount())
logger.Debug("Created shared UDP socket on port %d (refcount: %d)", port, sharedBind.GetRefCount())
// Parse DNS addresses
dnsAddrs := []netip.Addr{netip.MustParseAddr(dns)}
@@ -270,16 +270,21 @@ func (s *WireGuardService) SetOnNetstackClose(callback func()) {
}
// StartHolepunch starts hole punching to a specific endpoint
func (s *WireGuardService) StartHolepunch(publicKey string, endpoint string) {
func (s *WireGuardService) StartHolepunch(publicKey string, endpoint string, relayPort uint16) {
if s.holePunchManager == nil {
logger.Warn("Hole punch manager not initialized")
return
}
if relayPort == 0 {
relayPort = 21820
}
// Convert websocket.ExitNode to holepunch.ExitNode
hpExitNodes := []holepunch.ExitNode{
{
Endpoint: endpoint,
RelayPort: relayPort,
PublicKey: publicKey,
},
}
@@ -289,7 +294,7 @@ func (s *WireGuardService) StartHolepunch(publicKey string, endpoint string) {
logger.Warn("Failed to start hole punch: %v", err)
}
logger.Info("Starting hole punch to %s with public key: %s", endpoint, publicKey)
logger.Debug("Starting hole punch to %s with public key: %s", endpoint, publicKey)
}
// StartDirectUDPRelay starts a direct UDP relay from the main tunnel netstack to the clients' WireGuard.
@@ -336,7 +341,7 @@ func (s *WireGuardService) StartDirectUDPRelay(tunnelIP string) error {
// Set the netstack connection on the SharedBind so responses go back through the tunnel
s.sharedBind.SetNetstackConn(listener)
logger.Info("Started direct UDP relay on %s:%d (bidirectional via SharedBind)", tunnelIP, s.Port)
logger.Debug("Started direct UDP relay on %s:%d (bidirectional via SharedBind)", tunnelIP, s.Port)
// Start the relay goroutine to read from netstack and inject into SharedBind
s.directRelayWg.Add(1)
@@ -354,7 +359,7 @@ func (s *WireGuardService) runDirectUDPRelay(listener net.PacketConn) {
// Note: Don't close listener here - it's also used by SharedBind for sending responses
// It will be closed when the relay is stopped
logger.Info("Direct UDP relay started (bidirectional through SharedBind)")
logger.Debug("Direct UDP relay started (bidirectional through SharedBind)")
buf := make([]byte, 65535) // Max UDP packet size
@@ -440,7 +445,7 @@ func (s *WireGuardService) LoadRemoteConfig() error {
"port": s.Port,
}, 2*time.Second)
logger.Info("Requesting WireGuard configuration from remote server")
logger.Debug("Requesting WireGuard configuration from remote server")
go s.periodicBandwidthCheck()
return nil
@@ -450,7 +455,7 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
var config WgConfig
logger.Debug("Received message: %v", msg)
logger.Info("Received WireGuard clients configuration from remote server")
logger.Debug("Received WireGuard clients configuration from remote server")
jsonData, err := json.Marshal(msg.Data)
if err != nil {
@@ -472,6 +477,8 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
// Ensure the WireGuard interface and peers are configured
if err := s.ensureWireguardInterface(config); err != nil {
logger.Error("Failed to ensure WireGuard interface: %v", err)
logger.Error("Clients functionality will be disabled until the interface can be created")
return
}
if err := s.ensureWireguardPeers(config.Peers); err != nil {
@@ -481,6 +488,8 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
if err := s.ensureTargets(config.Targets); err != nil {
logger.Error("Failed to ensure WireGuard targets: %v", err)
}
logger.Info("Client connectivity setup. Ready to accept connections from clients!")
}
func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
@@ -628,7 +637,7 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
return fmt.Errorf("failed to bring up WireGuard device: %v", err)
}
logger.Info("WireGuard netstack device created and configured")
logger.Debug("WireGuard netstack device created and configured")
// Release the mutex before calling the callback
s.mu.Unlock()
@@ -647,6 +656,11 @@ func (s *WireGuardService) ensureWireguardPeers(peers []Peer) error {
// For netstack, we need to manage peers differently
// We'll configure peers directly on the device using IPC
// Check if device is initialized
if s.device == nil {
return fmt.Errorf("WireGuard device is not initialized")
}
// First, clear all existing peers by getting current config and removing them
currentConfig, err := s.device.IpcGet()
if err != nil {

View File

@@ -25,7 +25,7 @@
inherit (pkgs) lib;
# Update version when releasing
version = "1.7.0";
version = "1.8.0";
in
{
default = self.packages.${system}.pangolin-newt;
@@ -37,14 +37,26 @@
vendorHash = "sha256-5Xr6mwPtsqEliKeKv2rhhp6JC7u3coP4nnhIxGMqccU=";
nativeInstallCheckInputs = [ pkgs.versionCheckHook ];
env = {
CGO_ENABLED = 0;
};
ldflags = [
"-s"
"-w"
"-X main.newtVersion=${version}"
];
# Tests are broken due to a lack of Internet.
# Disable running `go test`, and instead do
# a simple version check instead.
doCheck = false;
doInstallCheck = true;
versionCheckProgramArg = [ "-version" ];
meta = {
description = "A tunneling client for Pangolin";
homepage = "https://github.com/fosrl/newt";
@@ -52,6 +64,7 @@
maintainers = [
lib.maintainers.water-sucks
];
mainProgram = "newt";
};
};
}

View File

@@ -61,6 +61,7 @@ type Target struct {
timer *time.Timer
ctx context.Context
cancel context.CancelFunc
client *http.Client
}
// StatusChangeCallback is called when any target's status changes
@@ -185,6 +186,16 @@ func (m *Monitor) addTargetUnsafe(config Config) error {
Status: StatusUnknown,
ctx: ctx,
cancel: cancel,
client: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
// Configure TLS settings based on certificate enforcement
InsecureSkipVerify: !m.enforceCert,
// Use SNI TLS header if present
ServerName: config.TLSServerName,
},
},
},
}
m.targets[config.ID] = target
@@ -378,17 +389,6 @@ func (m *Monitor) performHealthCheck(target *Target) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(target.Config.Timeout)*time.Second)
defer cancel()
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
// Configure TLS settings based on certificate enforcement
InsecureSkipVerify: !m.enforceCert,
// Use SNI TLS header if present
ServerName: target.Config.TLSServerName,
},
},
}
req, err := http.NewRequestWithContext(ctx, target.Config.Method, url, nil)
if err != nil {
target.Status = StatusUnhealthy
@@ -408,7 +408,7 @@ func (m *Monitor) performHealthCheck(target *Target) {
}
// Perform request
resp, err := client.Do(req)
resp, err := target.client.Do(req)
if err != nil {
target.Status = StatusUnhealthy
target.LastError = fmt.Sprintf("request failed: %v", err)

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net"
"strconv"
"sync"
"time"
@@ -19,7 +20,9 @@ import (
// ExitNode represents a WireGuard exit node for hole punching
type ExitNode struct {
Endpoint string `json:"endpoint"`
RelayPort uint16 `json:"relayPort"`
PublicKey string `json:"publicKey"`
SiteIds []int `json:"siteIds,omitempty"`
}
// Manager handles UDP hole punching operations
@@ -140,6 +143,51 @@ func (m *Manager) RemoveExitNode(endpoint string) bool {
return true
}
/*
RemoveExitNodesByPeer removes the peer ID from the SiteIds list in each exit node.
If the SiteIds list becomes empty after removal, the exit node is removed entirely.
Returns the number of exit nodes removed.
*/
func (m *Manager) RemoveExitNodesByPeer(peerID int) int {
m.mu.Lock()
defer m.mu.Unlock()
removed := 0
for endpoint, node := range m.exitNodes {
// Remove peerID from SiteIds if present
newSiteIds := make([]int, 0, len(node.SiteIds))
for _, id := range node.SiteIds {
if id != peerID {
newSiteIds = append(newSiteIds, id)
}
}
if len(newSiteIds) != len(node.SiteIds) {
node.SiteIds = newSiteIds
if len(node.SiteIds) == 0 {
delete(m.exitNodes, endpoint)
logger.Info("Removed exit node %s as no more site IDs remain after removing peer %d", endpoint, peerID)
removed++
} else {
m.exitNodes[endpoint] = node
logger.Info("Removed peer %d from exit node %s site IDs", peerID, endpoint)
}
}
}
if removed > 0 {
// Signal the goroutine to refresh if running
if m.running && m.updateChan != nil {
select {
case m.updateChan <- struct{}{}:
default:
// Channel full or closed, skip
}
}
}
return removed
}
// GetExitNodes returns a copy of the current exit nodes
func (m *Manager) GetExitNodes() []ExitNode {
m.mu.Lock()
@@ -202,7 +250,7 @@ func (m *Manager) TriggerHolePunch() error {
continue
}
serverAddr := net.JoinHostPort(host, "21820")
serverAddr := net.JoinHostPort(host, strconv.Itoa(int(exitNode.RelayPort)))
remoteAddr, err := net.ResolveUDPAddr("udp", serverAddr)
if err != nil {
logger.Error("Failed to resolve UDP address %s: %v", serverAddr, err)
@@ -247,7 +295,7 @@ func (m *Manager) StartMultipleExitNodes(exitNodes []ExitNode) error {
m.updateChan = make(chan struct{}, 1)
m.mu.Unlock()
logger.Info("Starting UDP hole punch to %d exit nodes with shared bind", len(exitNodes))
logger.Debug("Starting UDP hole punch to %d exit nodes with shared bind", len(exitNodes))
go m.runMultipleExitNodes()
@@ -313,7 +361,7 @@ func (m *Manager) runMultipleExitNodes() {
continue
}
serverAddr := net.JoinHostPort(host, "21820")
serverAddr := net.JoinHostPort(host, strconv.Itoa(int(exitNode.RelayPort)))
remoteAddr, err := net.ResolveUDPAddr("udp", serverAddr)
if err != nil {
logger.Error("Failed to resolve UDP address %s: %v", serverAddr, err)
@@ -325,7 +373,7 @@ func (m *Manager) runMultipleExitNodes() {
publicKey: exitNode.PublicKey,
endpointName: exitNode.Endpoint,
})
logger.Info("Resolved exit node: %s -> %s", exitNode.Endpoint, remoteAddr.String())
logger.Debug("Resolved exit node: %s -> %s", exitNode.Endpoint, remoteAddr.String())
}
return resolvedNodes
}

10
main.go
View File

@@ -37,6 +37,7 @@ import (
type WgData struct {
Endpoint string `json:"endpoint"`
RelayPort uint16 `json:"relayPort"`
PublicKey string `json:"publicKey"`
ServerIP string `json:"serverIP"`
TunnelIP string `json:"tunnelIP"`
@@ -419,7 +420,7 @@ func runNewtMain(ctx context.Context) {
}
if tel != nil {
// Admin HTTP server (exposes /metrics when Prometheus exporter is enabled)
logger.Info("Starting metrics server on %s", tcfg.AdminAddr)
logger.Debug("Starting metrics server on %s", tcfg.AdminAddr)
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })
if tel.PrometheusHandler != nil {
@@ -691,7 +692,12 @@ func runNewtMain(ctx context.Context) {
return
}
clientsHandleNewtConnection(wgData.PublicKey, endpoint)
relayPort := wgData.RelayPort
if relayPort == 0 {
relayPort = 21820
}
clientsHandleNewtConnection(wgData.PublicKey, endpoint, relayPort)
// Configure WireGuard
config := fmt.Sprintf(`private_key=%s

View File

@@ -372,7 +372,7 @@ func copyPacketData(dst, src net.PacketConn, to net.Addr, timeout time.Duration)
// InstallICMPHandler installs the ICMP handler on the stack
func (h *ICMPHandler) InstallICMPHandler() error {
h.stack.SetTransportProtocolHandler(header.ICMPv4ProtocolNumber, h.handleICMPPacket)
logger.Info("ICMP Handler: Installed ICMP protocol handler")
logger.Debug("ICMP Handler: Installed ICMP protocol handler")
return nil
}
@@ -600,7 +600,7 @@ func (h *ICMPHandler) sendAndReceiveICMP(conn *icmp.PacketConn, actualDstIP stri
logger.Debug("ICMP Handler: Reply seq mismatch: got seq=%d, want seq=%d", reply.Seq, seq)
continue
}
if !ignoreIdent && reply.ID != int(ident) {
logger.Debug("ICMP Handler: Reply ident mismatch: got ident=%d, want ident=%d", reply.ID, ident)
continue

View File

@@ -254,7 +254,7 @@ func NewProxyHandler(options ProxyHandlerOptions) (*ProxyHandler, error) {
if err := handler.icmpHandler.InstallICMPHandler(); err != nil {
return nil, fmt.Errorf("failed to install ICMP handler: %v", err)
}
logger.Info("ProxyHandler: ICMP handler enabled")
logger.Debug("ProxyHandler: ICMP handler enabled")
}
// // Example 1: Add a rule with no port restrictions (all ports allowed)
@@ -550,8 +550,8 @@ func (p *ProxyHandler) HandleIncomingPacket(packet []byte) bool {
return true
}
logger.Debug("HandleIncomingPacket: No matching rule for %s -> %s (proto=%d, port=%d)",
srcAddr, dstAddr, protocol, dstPort)
// logger.Debug("HandleIncomingPacket: No matching rule for %s -> %s (proto=%d, port=%d)",
// srcAddr, dstAddr, protocol, dstPort)
return false
}

View File

@@ -38,7 +38,6 @@ type Server struct {
isRunning bool
runningLock sync.Mutex
newtID string
outputPrefix string
useNetstack bool
tnet interface{} // Will be *netstack2.Net when using netstack
}
@@ -50,7 +49,6 @@ func NewServer(serverAddr string, serverPort uint16, newtID string) *Server {
serverPort: serverPort + 1, // use the next port for the server
shutdownCh: make(chan struct{}),
newtID: newtID,
outputPrefix: "[WGTester] ",
useNetstack: false,
tnet: nil,
}
@@ -63,7 +61,6 @@ func NewServerWithNetstack(serverAddr string, serverPort uint16, newtID string,
serverPort: serverPort + 1, // use the next port for the server
shutdownCh: make(chan struct{}),
newtID: newtID,
outputPrefix: "[WGTester] ",
useNetstack: true,
tnet: tnet,
}
@@ -109,7 +106,7 @@ func (s *Server) Start() error {
s.isRunning = true
go s.handleConnections()
logger.Info("%sServer started on %s:%d", s.outputPrefix, s.serverAddr, s.serverPort)
logger.Debug("WGTester Server started on %s:%d", s.serverAddr, s.serverPort)
return nil
}
@@ -127,7 +124,7 @@ func (s *Server) Stop() {
s.conn.Close()
}
s.isRunning = false
logger.Info("%sServer stopped", s.outputPrefix)
logger.Info("WGTester Server stopped")
}
// RestartWithNetstack stops the current server and restarts it with netstack
@@ -162,7 +159,7 @@ func (s *Server) handleConnections() {
// Set read deadline to avoid blocking forever
err := s.conn.SetReadDeadline(time.Now().Add(1 * time.Second))
if err != nil {
logger.Error("%sError setting read deadline: %v", s.outputPrefix, err)
logger.Error("Error setting read deadline: %v", err)
continue
}
@@ -192,7 +189,7 @@ func (s *Server) handleConnections() {
if err == io.EOF {
return
}
logger.Error("%sError reading from UDP: %v", s.outputPrefix, err)
logger.Error("Error reading from UDP: %v", err)
}
continue
}
@@ -224,7 +221,7 @@ func (s *Server) handleConnections() {
copy(responsePacket[5:13], buffer[5:13])
// Log response being sent for debugging
// logger.Debug("%sSending response to %s", s.outputPrefix, addr.String())
// logger.Debug("Sending response to %s", addr.String())
// Send the response packet - handle both regular UDP and netstack UDP
if s.useNetstack {
@@ -238,9 +235,9 @@ func (s *Server) handleConnections() {
}
if err != nil {
logger.Error("%sError sending response: %v", s.outputPrefix, err)
logger.Error("Error sending response: %v", err)
} else {
// logger.Debug("%sResponse sent successfully", s.outputPrefix)
// logger.Debug("Response sent successfully")
}
}
}