mirror of
https://github.com/fosrl/gerbil.git
synced 2026-02-08 05:56:40 +00:00
Compare commits
15 Commits
1.0.0-beta
...
1.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c04a6ecfd7 | ||
|
|
bc69b625fa | ||
|
|
1712b88e18 | ||
|
|
fc451baa06 | ||
|
|
fcb3b5de6a | ||
|
|
5101e6f125 | ||
|
|
217379d286 | ||
|
|
dc4297e6c4 | ||
|
|
b7f1d09d4d | ||
|
|
b44d320968 | ||
|
|
29a0f02ceb | ||
|
|
f0f63f22b4 | ||
|
|
91367f0e68 | ||
|
|
81a0ac576f | ||
|
|
ad0633c42d |
@@ -1,6 +1,12 @@
|
||||
## 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
|
||||
|
||||
@@ -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
|
||||
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.
|
||||
```
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@ Gerbil is a simple [WireGuard](https://www.wireguard.com/) interface management
|
||||
|
||||
### Installation and Documentation
|
||||
|
||||
Gerbil can be used stand alone with your own API, a static JSON file, or with Pangolin and Newt as part of the larger system. See documentation below:
|
||||
Gerbil can be used standalone with your own API, a static JSON file, or with Pangolin and Newt as part of the larger system. See documentation below:
|
||||
|
||||
- [Installation Instructions](https://docs.fossorial.io)
|
||||
- [Full Documentation](https://docs.fossorial.io)
|
||||
@@ -19,7 +19,7 @@ _Sample output of a Gerbil container connected to Pangolin and terminating vario
|
||||
|
||||
### Setup WireGuard
|
||||
|
||||
A WireGuard interface will be created and configured on the local Linux machine or in the Docker container according to the values given in either a JSON config file or via the remote server. If the interface already exists it will be reconfigured.
|
||||
A WireGuard interface will be created and configured on the local Linux machine or in the Docker container according to the values given in either a JSON config file or via the remote server. If the interface already exists, it will be reconfigured.
|
||||
|
||||
### Manage Peers
|
||||
|
||||
@@ -27,7 +27,7 @@ Gerbil will create the peers defined in the config on the WireGuard interface. T
|
||||
|
||||
### Report Bandwidth
|
||||
|
||||
Bytes transmitted in and out of each peer is collected every 10 seconds and incremental usage is reported via the "reportBandwidthTo" endpoint. This can be used to track data usage of each peer on the remote server.
|
||||
Bytes transmitted in and out of each peer are collected every 10 seconds, and incremental usage is reported via the "reportBandwidthTo" endpoint. This can be used to track data usage of each peer on the remote server.
|
||||
|
||||
## CLI Args
|
||||
|
||||
@@ -97,4 +97,4 @@ Gerbil is dual licensed under the AGPLv3 and the Fossorial Commercial license. F
|
||||
|
||||
## Contributions
|
||||
|
||||
Please see [CONTRIBUTIONS](./CONTRIBUTING.md) in the repository for guidelines and best practices.
|
||||
Please see [CONTRIBUTIONS](./CONTRIBUTING.md) in the repository for guidelines and best practices.
|
||||
|
||||
14
SECURITY.md
Normal file
14
SECURITY.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Security Policy
|
||||
|
||||
If you discover a security vulnerability, please follow the steps below to responsibly disclose it to us:
|
||||
|
||||
1. **Do not create a public GitHub issue or discussion post.** This could put the security of other users at risk.
|
||||
2. Send a detailed report to [security@fossorial.io](mailto:security@fossorial.io) or send a **private** message to a maintainer on [Discord](https://discord.gg/HCJR8Xhme4). Include:
|
||||
|
||||
- Description and location of the vulnerability.
|
||||
- Potential impact of the vulnerability.
|
||||
- Steps to reproduce the vulnerability.
|
||||
- Potential solutions to fix the vulnerability.
|
||||
- Your name/handle and a link for recognition (optional).
|
||||
|
||||
We aim to address the issue as soon as possible.
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Sample from https://github.com/traefik/traefik-library-image/blob/5070edb25b03cca6802d75d5037576c840f73fdd/v3.1/alpine/entrypoint.sh
|
||||
|
||||
set -e
|
||||
|
||||
# first arg is `-f` or `--some-option`
|
||||
@@ -9,13 +7,4 @@ if [ "${1#-}" != "$1" ]; then
|
||||
set -- gerbil "$@"
|
||||
fi
|
||||
|
||||
# if our command is a valid Gerbil subcommand, let's invoke it through Gerbil instead
|
||||
# (this allows for "docker run gerbil version", etc)
|
||||
if gerbil "$1" --help >/dev/null 2>&1
|
||||
then
|
||||
set -- gerbil "$@"
|
||||
else
|
||||
echo "= '$1' is not a Gerbil command: assuming shell execution." 1>&2
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
108
main.go
108
main.go
@@ -9,6 +9,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -20,8 +21,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
interfaceName = "wg0"
|
||||
listenAddr = ":3003"
|
||||
interfaceName string
|
||||
listenAddr string
|
||||
mtuInt int
|
||||
lastReadings = make(map[string]PeerReading)
|
||||
mu sync.Mutex
|
||||
)
|
||||
@@ -72,52 +74,91 @@ func parseLogLevel(level string) logger.LogLevel {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var wgconfig WgConfig
|
||||
var (
|
||||
err error
|
||||
wgconfig WgConfig
|
||||
configFile string
|
||||
remoteConfigURL string
|
||||
reportBandwidthTo string
|
||||
generateAndSaveKeyTo string
|
||||
reachableAt string
|
||||
logLevel string
|
||||
mtu string
|
||||
)
|
||||
|
||||
// Define command line flags
|
||||
interfaceNameArg := flag.String("interface", "wg0", "Name of the WireGuard interface")
|
||||
configFile := flag.String("config", "", "Path to local configuration file")
|
||||
remoteConfigURL := flag.String("remoteConfig", "", "URL to fetch remote configuration")
|
||||
listenAddrArg := flag.String("listen", ":3003", "Address to listen on")
|
||||
reportBandwidthTo := flag.String("reportBandwidthTo", "", "Address to listen on")
|
||||
generateAndSaveKeyTo := flag.String("generateAndSaveKeyTo", "", "Path to save generated private key")
|
||||
reachableAt := flag.String("reachableAt", "", "Endpoint of the http server to tell remote config about")
|
||||
logLevel := flag.String("log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)")
|
||||
interfaceName = os.Getenv("INTERFACE")
|
||||
configFile = os.Getenv("CONFIG")
|
||||
remoteConfigURL = os.Getenv("REMOTE_CONFIG")
|
||||
listenAddr = os.Getenv("LISTEN")
|
||||
reportBandwidthTo = os.Getenv("REPORT_BANDWIDTH_TO")
|
||||
generateAndSaveKeyTo = os.Getenv("GENERATE_AND_SAVE_KEY_TO")
|
||||
reachableAt = os.Getenv("REACHABLE_AT")
|
||||
logLevel = os.Getenv("LOG_LEVEL")
|
||||
mtu = os.Getenv("MTU")
|
||||
|
||||
if interfaceName == "" {
|
||||
flag.StringVar(&interfaceName, "interface", "wg0", "Name of the WireGuard interface")
|
||||
}
|
||||
if configFile == "" {
|
||||
flag.StringVar(&configFile, "config", "", "Path to local configuration file")
|
||||
}
|
||||
if remoteConfigURL == "" {
|
||||
flag.StringVar(&remoteConfigURL, "remoteConfig", "", "URL to fetch remote configuration")
|
||||
}
|
||||
if listenAddr == "" {
|
||||
flag.StringVar(&listenAddr, "listen", ":3003", "Address to listen on")
|
||||
}
|
||||
if reportBandwidthTo == "" {
|
||||
flag.StringVar(&reportBandwidthTo, "reportBandwidthTo", "", "Address to listen on")
|
||||
}
|
||||
if generateAndSaveKeyTo == "" {
|
||||
flag.StringVar(&generateAndSaveKeyTo, "generateAndSaveKeyTo", "", "Path to save generated private key")
|
||||
}
|
||||
if reachableAt == "" {
|
||||
flag.StringVar(&reachableAt, "reachableAt", "", "Endpoint of the http server to tell remote config about")
|
||||
}
|
||||
if logLevel == "" {
|
||||
flag.StringVar(&logLevel, "log-level", "INFO", "Log level (DEBUG, INFO, WARN, ERROR, FATAL)")
|
||||
}
|
||||
if mtu == "" {
|
||||
flag.StringVar(&mtu, "mtu", "1280", "MTU of the WireGuard interface")
|
||||
}
|
||||
flag.Parse()
|
||||
|
||||
logger.Init()
|
||||
logger.GetLogger().SetLevel(parseLogLevel(*logLevel))
|
||||
logger.GetLogger().SetLevel(parseLogLevel(logLevel))
|
||||
|
||||
if *interfaceNameArg != "" {
|
||||
interfaceName = *interfaceNameArg
|
||||
}
|
||||
if *listenAddrArg != "" {
|
||||
listenAddr = *listenAddrArg
|
||||
mtuInt, err = strconv.Atoi(mtu)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to parse MTU: %v", err)
|
||||
}
|
||||
|
||||
// Validate that only one config option is provided
|
||||
if (*configFile != "" && *remoteConfigURL != "") || (*configFile == "" && *remoteConfigURL == "") {
|
||||
logger.Fatal("Please provide either --config or --remoteConfig, but not both")
|
||||
// are they missing either the config file or the remote config URL?
|
||||
if configFile == "" && remoteConfigURL == "" {
|
||||
logger.Fatal("You must provide either a config file or a remote config URL")
|
||||
}
|
||||
|
||||
// do they have both the config file and the remote config URL?
|
||||
if configFile != "" && remoteConfigURL != "" {
|
||||
logger.Fatal("You must provide either a config file or a remote config URL, not both")
|
||||
}
|
||||
|
||||
var key wgtypes.Key
|
||||
// if generateAndSaveKeyTo is provided, generate a private key and save it to the file. if the file already exists, load the key from the file
|
||||
if *generateAndSaveKeyTo != "" {
|
||||
if _, err := os.Stat(*generateAndSaveKeyTo); os.IsNotExist(err) {
|
||||
if generateAndSaveKeyTo != "" {
|
||||
if _, err := os.Stat(generateAndSaveKeyTo); os.IsNotExist(err) {
|
||||
// generate a new private key
|
||||
key, err = wgtypes.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to generate private key: %v", err)
|
||||
}
|
||||
// save the key to the file
|
||||
err = os.WriteFile(*generateAndSaveKeyTo, []byte(key.String()), 0644)
|
||||
err = os.WriteFile(generateAndSaveKeyTo, []byte(key.String()), 0644)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to save private key: %v", err)
|
||||
}
|
||||
} else {
|
||||
keyData, err := os.ReadFile(*generateAndSaveKeyTo)
|
||||
keyData, err := os.ReadFile(generateAndSaveKeyTo)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to read private key: %v", err)
|
||||
}
|
||||
@@ -138,8 +179,8 @@ func main() {
|
||||
}
|
||||
|
||||
// Load configuration based on provided argument
|
||||
if *configFile != "" {
|
||||
wgconfig, err = loadConfig(*configFile)
|
||||
if configFile != "" {
|
||||
wgconfig, err = loadConfig(configFile)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to load configuration: %v", err)
|
||||
}
|
||||
@@ -147,7 +188,7 @@ func main() {
|
||||
wgconfig.PrivateKey = key.String()
|
||||
}
|
||||
} else {
|
||||
wgconfig, err = loadRemoteConfig(*remoteConfigURL, key, *reachableAt)
|
||||
wgconfig, err = loadRemoteConfig(remoteConfigURL, key, reachableAt)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to load configuration: %v", err)
|
||||
}
|
||||
@@ -168,8 +209,8 @@ func main() {
|
||||
// Ensure the WireGuard peers exist
|
||||
ensureWireguardPeers(wgconfig.Peers)
|
||||
|
||||
if *reportBandwidthTo != "" {
|
||||
go periodicBandwidthCheck(*reportBandwidthTo)
|
||||
if reportBandwidthTo != "" {
|
||||
go periodicBandwidthCheck(reportBandwidthTo)
|
||||
}
|
||||
|
||||
http.HandleFunc("/peer", handlePeer)
|
||||
@@ -288,6 +329,11 @@ func ensureWireguardInterface(wgconfig WgConfig) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get interface: %v", err)
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetMTU(link, mtuInt); err != nil {
|
||||
return fmt.Errorf("failed to set MTU: %v", err)
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetUp(link); err != nil {
|
||||
return fmt.Errorf("failed to bring up interface: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user