Compare commits

...

11 Commits

Author SHA1 Message Date
Owen Schwartz
313afdb4c5 Merge pull request #3 from fosrl/dev
Allow use of env vars, docs, and ping interval
2025-01-07 22:36:53 -05:00
Owen Schwartz
235a3b9426 Fix docker compose 2025-01-07 21:45:30 -05:00
Owen Schwartz
c298ff52f3 Update readme 2025-01-07 21:16:21 -05:00
Owen Schwartz
75518b2e04 Ping interval 2025-01-07 21:12:07 -05:00
Owen Schwartz
739f708ff7 Update sample docker-compose 2025-01-07 20:52:38 -05:00
Owen Schwartz
2897b92f72 Allow use of env vars 2025-01-07 20:51:33 -05:00
Milo Schwartz
2c612d4018 Merge pull request #2 from fosrl/dev
update CONTRIBUTING.md
2025-01-06 22:46:03 -05:00
Milo Schwartz
41f0973308 update CONTRIBUTING.md 2025-01-06 22:28:20 -05:00
Owen Schwartz
4a791bdb6e Merge branch 'main' of https://github.com/fosrl/newt 2025-01-04 23:52:24 -05:00
Owen Schwartz
9497f9c96f Update readme 2025-01-04 23:52:18 -05:00
Milo Schwartz
e17276b0c4 fix typo in log 2025-01-04 22:58:41 -05:00
5 changed files with 86 additions and 29 deletions

View File

@@ -1,6 +1,12 @@
## Contributing ## Contributing
Contributions are welcome! Please see the following page in our documentation with future plans and feature ideas if you are looking for a place to start. Contributions are welcome!
Please see the contribution and local development guide on the docs page before getting started:
https://docs.fossorial.io/development
For ideas about what features to work on and our future plans, please see the roadmap:
https://docs.fossorial.io/roadmap https://docs.fossorial.io/roadmap
@@ -15,4 +21,4 @@ By creating this pull request, I grant the project maintainers an unlimited,
perpetual license to use, modify, and redistribute these contributions under any terms they perpetual license to use, modify, and redistribute these contributions under any terms they
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content. represent that I have the right to grant this license for all contributed content.
``` ```

View File

@@ -46,6 +46,22 @@ Example:
--endpoint https://example.com --endpoint https://example.com
``` ```
You can also run it with Docker compose. For example, a service in your `docker-compose.yml` might look like this using environment vars (recommended):
```yaml
services:
newt:
image: fosrl/newt
container_name: newt
restart: unless-stopped
environment:
- PANGOLIN_ENDPOINT=https://example.com
- NEWT_ID=2ix2t8xk22ubpfy
- NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2
```
You can also pass the CLI args to the container:
```yaml ```yaml
services: services:
newt: newt:
@@ -53,8 +69,8 @@ services:
container_name: newt container_name: newt
restart: unless-stopped restart: unless-stopped
command: command:
- --id 31frd0uzbjvp721 \ - --id 31frd0uzbjvp721
- --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 \ - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6
- --endpoint https://example.com - --endpoint https://example.com
``` ```

9
docker-compose.yml Normal file
View File

@@ -0,0 +1,9 @@
services:
newt:
image: fosrl/newt:latest
container_name: newt
restart: unless-stopped
environment:
- PANGOLIN_ENDPOINT=https://example.com
- NEWT_ID=2ix2t8xk22ubpfy
- NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2

View File

@@ -1,7 +1,5 @@
#!/bin/sh #!/bin/sh
# Sample from https://github.com/traefik/traefik-library-image/blob/5070edb25b03cca6802d75d5037576c840f73fdd/v3.1/alpine/entrypoint.sh
set -e set -e
# first arg is `-f` or `--some-option` # first arg is `-f` or `--some-option`
@@ -9,13 +7,4 @@ if [ "${1#-}" != "$1" ]; then
set -- newt "$@" set -- newt "$@"
fi fi
# if our command is a valid newt subcommand, let's invoke it through newt instead
# (this allows for "docker run newt version", etc)
if newt "$1" --help >/dev/null 2>&1
then
set -- newt "$@"
else
echo "= '$1' is not a newt command: assuming shell execution." 1>&2
fi
exec "$@" exec "$@"

65
main.go
View File

@@ -112,6 +112,26 @@ func ping(tnet *netstack.Net, dst string) error {
return nil return nil
} }
func startPingCheck(tnet *netstack.Net, serverIP string, stopChan chan struct{}) {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
go func() {
for {
select {
case <-ticker.C:
err := ping(tnet, serverIP)
if err != nil {
logger.Warn("Periodic ping failed: %v", err)
}
case <-stopChan:
logger.Info("Stopping ping check")
return
}
}
}()
}
func pingWithRetry(tnet *netstack.Net, dst string) error { func pingWithRetry(tnet *netstack.Net, dst string) error {
const ( const (
maxAttempts = 5 maxAttempts = 5
@@ -222,13 +242,6 @@ func resolveDomain(domain string) (string, error) {
return ipAddr, nil return ipAddr, nil
} }
func getEnvWithDefault(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
func main() { func main() {
var ( var (
endpoint string endpoint string
@@ -240,12 +253,28 @@ func main() {
logLevel string logLevel string
) )
// Define CLI flags with default values from environment variables // if PANGOLIN_ENDPOINT, NEWT_ID, and NEWT_SECRET are set as environment variables, they will be used as default values
flag.StringVar(&endpoint, "endpoint", os.Getenv("PANGOLIN_ENDPOINT"), "Endpoint of your pangolin server") endpoint = os.Getenv("PANGOLIN_ENDPOINT")
flag.StringVar(&id, "id", os.Getenv("NEWT_ID"), "Newt ID") id = os.Getenv("NEWT_ID")
flag.StringVar(&secret, "secret", os.Getenv("NEWT_SECRET"), "Newt secret") secret = os.Getenv("NEWT_SECRET")
flag.StringVar(&dns, "dns", getEnvWithDefault("DEFAULT_DNS", "8.8.8.8"), "DNS server to use") dns = os.Getenv("DNS")
flag.StringVar(&logLevel, "log-level", getEnvWithDefault("LOG_LEVEL", "INFO"), "Log level (DEBUG, INFO, WARN, ERROR, FATAL)") logLevel = os.Getenv("LOG_LEVEL")
if endpoint == "" {
flag.StringVar(&endpoint, "endpoint", "", "Endpoint of your pangolin server")
}
if id == "" {
flag.StringVar(&id, "id", "", "Newt ID")
}
if secret == "" {
flag.StringVar(&secret, "secret", "", "Newt secret")
}
if dns == "" {
flag.StringVar(&dns, "dns", "8.8.8.8", "DNS server to use")
}
if logLevel == "" {
flag.StringVar(&logLevel, "log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)")
}
flag.Parse() flag.Parse()
logger.Init() logger.Init()
@@ -291,12 +320,15 @@ func main() {
client.Close() client.Close()
}) })
pingStopChan := make(chan struct{})
defer close(pingStopChan)
// Register handlers for different message types // Register handlers for different message types
client.RegisterHandler("newt/wg/connect", func(msg websocket.WSMessage) { client.RegisterHandler("newt/wg/connect", func(msg websocket.WSMessage) {
logger.Info("Received registration message") logger.Info("Received registration message")
if connected { if connected {
logger.Info("Already connected! Put I will send a ping anyway...") logger.Info("Already connected! But I will send a ping anyway...")
// ping(tnet, wgData.ServerIP) // ping(tnet, wgData.ServerIP)
err = pingWithRetry(tnet, wgData.ServerIP) err = pingWithRetry(tnet, wgData.ServerIP)
if err != nil { if err != nil {
@@ -365,6 +397,11 @@ persistent_keepalive_interval=5`, fixKey(fmt.Sprintf("%s", privateKey)), fixKey(
logger.Error("Failed to ping %s: %v", wgData.ServerIP, err) logger.Error("Failed to ping %s: %v", wgData.ServerIP, err)
} }
if !connected {
logger.Info("Starting ping check")
startPingCheck(tnet, wgData.ServerIP, pingStopChan)
}
// Create proxy manager // Create proxy manager
pm = proxy.NewProxyManager(tnet) pm = proxy.NewProxyManager(tnet)