Compare commits

...

11 Commits

Author SHA1 Message Date
Owen
d754cea397 Dont run on v tags 2025-12-23 17:54:31 -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
3d5335f2cb Add back release and binaries 2025-12-21 21:00:45 -05:00
13 changed files with 128 additions and 29 deletions

View File

@@ -11,7 +11,9 @@ permissions:
on: on:
push: push:
tags: tags:
- "*" - "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+"
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: version:
@@ -273,7 +275,7 @@ jobs:
tags: | tags: |
type=semver,pattern={{version}},value=${{ env.TAG }} 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=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: | flavor: |
latest=false latest=false
labels: | labels: |
@@ -594,7 +596,7 @@ jobs:
run: | run: |
set -euo pipefail set -euo pipefail
TAG_VAR="${TAG}" TAG_VAR="${TAG}"
make go-build-release tag=$TAG_VAR make -j 10 go-build-release tag=$TAG_VAR
shell: bash shell: bash
- name: Create GitHub Release - name: Create GitHub Release

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

2
.gitignore vendored
View File

@@ -6,3 +6,5 @@ nohup.out
certs/ certs/
newt_arm64 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-darwin-amd64 go-build-release-windows-amd64 \
go-build-release-freebsd-amd64 go-build-release-freebsd-arm64 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: go-build-release-linux-arm64:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/newt_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, "/") 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 is true make sure we have permission to use native interface
if useNativeInterface { if useNativeInterface {

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) // Add a reference for the hole punch manager (creator already has one reference for WireGuard)
sharedBind.AddRef() 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 // Parse DNS addresses
dnsAddrs := []netip.Addr{netip.MustParseAddr(dns)} dnsAddrs := []netip.Addr{netip.MustParseAddr(dns)}
@@ -294,7 +294,7 @@ func (s *WireGuardService) StartHolepunch(publicKey string, endpoint string, rel
logger.Warn("Failed to start hole punch: %v", err) 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. // StartDirectUDPRelay starts a direct UDP relay from the main tunnel netstack to the clients' WireGuard.
@@ -341,7 +341,7 @@ func (s *WireGuardService) StartDirectUDPRelay(tunnelIP string) error {
// Set the netstack connection on the SharedBind so responses go back through the tunnel // Set the netstack connection on the SharedBind so responses go back through the tunnel
s.sharedBind.SetNetstackConn(listener) 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 // Start the relay goroutine to read from netstack and inject into SharedBind
s.directRelayWg.Add(1) s.directRelayWg.Add(1)
@@ -359,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 // Note: Don't close listener here - it's also used by SharedBind for sending responses
// It will be closed when the relay is stopped // 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 buf := make([]byte, 65535) // Max UDP packet size
@@ -445,7 +445,7 @@ func (s *WireGuardService) LoadRemoteConfig() error {
"port": s.Port, "port": s.Port,
}, 2*time.Second) }, 2*time.Second)
logger.Info("Requesting WireGuard configuration from remote server") logger.Debug("Requesting WireGuard configuration from remote server")
go s.periodicBandwidthCheck() go s.periodicBandwidthCheck()
return nil return nil
@@ -455,7 +455,7 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
var config WgConfig var config WgConfig
logger.Debug("Received message: %v", msg) 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) jsonData, err := json.Marshal(msg.Data)
if err != nil { if err != nil {
@@ -488,6 +488,8 @@ func (s *WireGuardService) handleConfig(msg websocket.WSMessage) {
if err := s.ensureTargets(config.Targets); err != nil { if err := s.ensureTargets(config.Targets); err != nil {
logger.Error("Failed to ensure WireGuard targets: %v", err) 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 { func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
@@ -635,7 +637,7 @@ func (s *WireGuardService) ensureWireguardInterface(wgconfig WgConfig) error {
return fmt.Errorf("failed to bring up WireGuard device: %v", err) 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 // Release the mutex before calling the callback
s.mu.Unlock() s.mu.Unlock()

View File

@@ -25,7 +25,7 @@
inherit (pkgs) lib; inherit (pkgs) lib;
# Update version when releasing # Update version when releasing
version = "1.7.0"; version = "1.8.0";
in in
{ {
default = self.packages.${system}.pangolin-newt; default = self.packages.${system}.pangolin-newt;
@@ -37,14 +37,26 @@
vendorHash = "sha256-5Xr6mwPtsqEliKeKv2rhhp6JC7u3coP4nnhIxGMqccU="; vendorHash = "sha256-5Xr6mwPtsqEliKeKv2rhhp6JC7u3coP4nnhIxGMqccU=";
nativeInstallCheckInputs = [ pkgs.versionCheckHook ];
env = { env = {
CGO_ENABLED = 0; CGO_ENABLED = 0;
}; };
ldflags = [ ldflags = [
"-s"
"-w"
"-X main.newtVersion=${version}" "-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 = { meta = {
description = "A tunneling client for Pangolin"; description = "A tunneling client for Pangolin";
homepage = "https://github.com/fosrl/newt"; homepage = "https://github.com/fosrl/newt";
@@ -52,6 +64,7 @@
maintainers = [ maintainers = [
lib.maintainers.water-sucks lib.maintainers.water-sucks
]; ];
mainProgram = "newt";
}; };
}; };
} }

View File

@@ -295,7 +295,7 @@ func (m *Manager) StartMultipleExitNodes(exitNodes []ExitNode) error {
m.updateChan = make(chan struct{}, 1) m.updateChan = make(chan struct{}, 1)
m.mu.Unlock() 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() go m.runMultipleExitNodes()
@@ -373,7 +373,7 @@ func (m *Manager) runMultipleExitNodes() {
publicKey: exitNode.PublicKey, publicKey: exitNode.PublicKey,
endpointName: exitNode.Endpoint, 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 return resolvedNodes
} }

View File

@@ -420,7 +420,7 @@ func runNewtMain(ctx context.Context) {
} }
if tel != nil { if tel != nil {
// Admin HTTP server (exposes /metrics when Prometheus exporter is enabled) // 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 := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) }) mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })
if tel.PrometheusHandler != nil { if tel.PrometheusHandler != nil {

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 // InstallICMPHandler installs the ICMP handler on the stack
func (h *ICMPHandler) InstallICMPHandler() error { func (h *ICMPHandler) InstallICMPHandler() error {
h.stack.SetTransportProtocolHandler(header.ICMPv4ProtocolNumber, h.handleICMPPacket) 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 return nil
} }

View File

@@ -254,7 +254,7 @@ func NewProxyHandler(options ProxyHandlerOptions) (*ProxyHandler, error) {
if err := handler.icmpHandler.InstallICMPHandler(); err != nil { if err := handler.icmpHandler.InstallICMPHandler(); err != nil {
return nil, fmt.Errorf("failed to install ICMP handler: %v", err) 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) // // Example 1: Add a rule with no port restrictions (all ports allowed)

View File

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