mirror of
https://github.com/fosrl/gerbil.git
synced 2026-02-12 07:56:43 +00:00
Compare commits
10 Commits
1.0.0-beta
...
1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cba4dc646d | ||
|
|
88be6d133d | ||
|
|
34a80c6411 | ||
|
|
6565fdbe62 | ||
|
|
9c5ddcdfb8 | ||
|
|
32176c74a0 | ||
|
|
aa4f4ebfab | ||
|
|
bab8630756 | ||
|
|
24e993ee41 | ||
|
|
5d4faaff65 |
52
.github/workflows/cicd.yml
vendored
Normal file
52
.github/workflows/cicd.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
name: CI/CD Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Build and Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract tag name
|
||||||
|
id: get-tag
|
||||||
|
run: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: 1.23.1
|
||||||
|
|
||||||
|
- name: Build and push Docker images
|
||||||
|
run: |
|
||||||
|
TAG=${{ env.TAG }}
|
||||||
|
make docker-build-release tag=$TAG
|
||||||
|
|
||||||
|
- name: Build binaries
|
||||||
|
run: |
|
||||||
|
make go-build-release
|
||||||
|
|
||||||
|
- name: Upload artifacts from /bin
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: binaries
|
||||||
|
path: bin/
|
||||||
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
gerbil
|
gerbil
|
||||||
|
.DS_Store
|
||||||
|
bin/
|
||||||
@@ -18,6 +18,8 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o /gerbil
|
|||||||
# Start a new stage from scratch
|
# Start a new stage from scratch
|
||||||
FROM ubuntu:22.04 AS runner
|
FROM ubuntu:22.04 AS runner
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y iptables iproute2 && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy the pre-built binary file from the previous stage and the entrypoint script
|
# Copy the pre-built binary file from the previous stage and the entrypoint script
|
||||||
COPY --from=builder /gerbil /usr/local/bin/
|
COPY --from=builder /gerbil /usr/local/bin/
|
||||||
COPY entrypoint.sh /
|
COPY entrypoint.sh /
|
||||||
|
|||||||
14
Makefile
14
Makefile
@@ -1,6 +1,14 @@
|
|||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
docker-build-release:
|
||||||
|
@if [ -z "$(tag)" ]; then \
|
||||||
|
echo "Error: tag is required. Usage: make build-all tag=<tag>"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/gerbil:latest -f Dockerfile --push .
|
||||||
|
docker buildx build --platform linux/arm64,linux/amd64 -t fosrl/gerbil:$(tag) -f Dockerfile --push .
|
||||||
|
|
||||||
build:
|
build:
|
||||||
docker build -t fosrl/gerbil:latest .
|
docker build -t fosrl/gerbil:latest .
|
||||||
|
|
||||||
@@ -13,5 +21,9 @@ test:
|
|||||||
local:
|
local:
|
||||||
CGO_ENABLED=0 GOOS=linux go build -o gerbil
|
CGO_ENABLED=0 GOOS=linux go build -o gerbil
|
||||||
|
|
||||||
|
go-build-release:
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/gerbil_linux_arm64
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/gerbil_linux_amd64
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm gerbil
|
rm gerbil
|
||||||
|
|||||||
107
main.go
107
main.go
@@ -9,6 +9,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -188,11 +189,17 @@ func main() {
|
|||||||
wgconfig.PrivateKey = key.String()
|
wgconfig.PrivateKey = key.String()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wgconfig, err = loadRemoteConfig(remoteConfigURL, key, reachableAt)
|
// loop until we get the config
|
||||||
if err != nil {
|
for wgconfig.PrivateKey == "" {
|
||||||
logger.Fatal("Failed to load configuration: %v", err)
|
logger.Info("Fetching remote config from %s", remoteConfigURL)
|
||||||
|
wgconfig, err = loadRemoteConfig(remoteConfigURL, key, reachableAt)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to load configuration: %v", err)
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wgconfig.PrivateKey = key.String()
|
||||||
}
|
}
|
||||||
wgconfig.PrivateKey = key.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wgClient, err = wgctrl.New()
|
wgClient, err = wgctrl.New()
|
||||||
@@ -338,6 +345,10 @@ func ensureWireguardInterface(wgconfig WgConfig) error {
|
|||||||
return fmt.Errorf("failed to bring up interface: %v", err)
|
return fmt.Errorf("failed to bring up interface: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ensureMSSClamping(); err != nil {
|
||||||
|
logger.Warn("Failed to ensure MSS clamping: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("WireGuard interface %s created and configured", interfaceName)
|
logger.Info("WireGuard interface %s created and configured", interfaceName)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -415,6 +426,94 @@ func ensureWireguardPeers(peers []Peer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureMSSClamping() error {
|
||||||
|
// Calculate MSS value (MTU - 40 for IPv4 header (20) and TCP header (20))
|
||||||
|
mssValue := mtuInt - 40
|
||||||
|
|
||||||
|
// Rules to be managed - just the chains, we'll construct the full command separately
|
||||||
|
chains := []string{"INPUT", "OUTPUT", "FORWARD"}
|
||||||
|
|
||||||
|
// First, try to delete any existing rules
|
||||||
|
for _, chain := range chains {
|
||||||
|
deleteCmd := exec.Command("/usr/sbin/iptables",
|
||||||
|
"-t", "mangle",
|
||||||
|
"-D", chain,
|
||||||
|
"-p", "tcp",
|
||||||
|
"--tcp-flags", "SYN,RST", "SYN",
|
||||||
|
"-j", "TCPMSS",
|
||||||
|
"--set-mss", fmt.Sprintf("%d", mssValue))
|
||||||
|
|
||||||
|
logger.Info("Attempting to delete existing MSS clamping rule for chain %s", chain)
|
||||||
|
|
||||||
|
// Try deletion multiple times to handle multiple existing rules
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
out, err := deleteCmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
// Convert exit status 1 to string for better logging
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
logger.Debug("Deletion stopped for chain %s: %v (output: %s)",
|
||||||
|
chain, exitErr.String(), string(out))
|
||||||
|
}
|
||||||
|
break // No more rules to delete
|
||||||
|
}
|
||||||
|
logger.Info("Deleted MSS clamping rule for chain %s (attempt %d)", chain, i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add the new rules
|
||||||
|
var errors []error
|
||||||
|
for _, chain := range chains {
|
||||||
|
addCmd := exec.Command("/usr/sbin/iptables",
|
||||||
|
"-t", "mangle",
|
||||||
|
"-A", chain,
|
||||||
|
"-p", "tcp",
|
||||||
|
"--tcp-flags", "SYN,RST", "SYN",
|
||||||
|
"-j", "TCPMSS",
|
||||||
|
"--set-mss", fmt.Sprintf("%d", mssValue))
|
||||||
|
|
||||||
|
logger.Info("Adding MSS clamping rule for chain %s", chain)
|
||||||
|
|
||||||
|
if out, err := addCmd.CombinedOutput(); err != nil {
|
||||||
|
errMsg := fmt.Sprintf("Failed to add MSS clamping rule for chain %s: %v (output: %s)",
|
||||||
|
chain, err, string(out))
|
||||||
|
logger.Error(errMsg)
|
||||||
|
errors = append(errors, fmt.Errorf(errMsg))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the rule was added
|
||||||
|
checkCmd := exec.Command("/usr/sbin/iptables",
|
||||||
|
"-t", "mangle",
|
||||||
|
"-C", chain,
|
||||||
|
"-p", "tcp",
|
||||||
|
"--tcp-flags", "SYN,RST", "SYN",
|
||||||
|
"-j", "TCPMSS",
|
||||||
|
"--set-mss", fmt.Sprintf("%d", mssValue))
|
||||||
|
|
||||||
|
if out, err := checkCmd.CombinedOutput(); err != nil {
|
||||||
|
errMsg := fmt.Sprintf("Rule verification failed for chain %s: %v (output: %s)",
|
||||||
|
chain, err, string(out))
|
||||||
|
logger.Error(errMsg)
|
||||||
|
errors = append(errors, fmt.Errorf(errMsg))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Successfully added and verified MSS clamping rule for chain %s", chain)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we encountered any errors, return them combined
|
||||||
|
if len(errors) > 0 {
|
||||||
|
var errMsgs []string
|
||||||
|
for _, err := range errors {
|
||||||
|
errMsgs = append(errMsgs, err.Error())
|
||||||
|
}
|
||||||
|
return fmt.Errorf("MSS clamping setup encountered errors:\n%s",
|
||||||
|
strings.Join(errMsgs, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func handlePeer(w http.ResponseWriter, r *http.Request) {
|
func handlePeer(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
|
|||||||
Reference in New Issue
Block a user