chore: initial commit of wgtool

This commit is contained in:
sapient
2026-03-22 00:54:58 -07:00
commit f9529c6055
59 changed files with 6102 additions and 0 deletions

360
GO_VS_BASH_ANALYSIS.md Normal file
View File

@@ -0,0 +1,360 @@
# Go vs Bash Implementation Analysis
## Overview
This document compares the bash implementation (`wireguard_setup.sh`) with the Go implementation (`wireguard_setup.go`) and identifies key improvements and advantages of the Go version.
## Key Improvements in Go Version
### 1. **Type Safety and Error Handling**
**Bash Version:**
```bash
# Basic string validation
if [ -z "$NODE_NAME" ]; then
print_error "Node name cannot be empty"
exit 1
fi
```
**Go Version:**
```go
// Strong typing with structured validation
func validateHostname(hostname string) error {
if hostname == "" {
return fmt.Errorf("hostname cannot be empty")
}
if len(hostname) > 63 {
return fmt.Errorf("hostname too long (max 63 characters)")
}
hostnameRegex := regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$|^[a-zA-Z0-9]$`)
if !hostnameRegex.MatchString(hostname) {
return fmt.Errorf("invalid hostname format. Use alphanumeric characters and hyphens only")
}
return nil
}
```
**Advantages:**
- Compile-time error checking
- Structured error handling with context
- Type safety prevents runtime errors
- Better validation with regex patterns
### 2. **Configuration Management**
**Bash Version:**
```bash
# Hardcoded values scattered throughout
ZION_PUBLIC_KEY="2ztJbrN1x1NWanzPGLiKL19ZkdOhm5Y7WeKEWBT5cyg="
ZION_ENDPOINT="ugh.im:51820"
ZION_ALLOWED_IPS="10.8.0.0/24"
```
**Go Version:**
```go
// Structured configuration with type safety
type ZionConfig struct {
PublicKey string `json:"public_key"`
Endpoint string `json:"endpoint"`
Peers map[string]string `json:"peers"` // name -> public_key
}
var zionConfig = ZionConfig{
PublicKey: "2ztJbrN1x1NWanzPGLiKL19ZkdOhm5Y7WeKEWBT5cyg=",
Endpoint: "ugh.im:51820",
Peers: map[string]string{
"Cth": "NBktXKy1s0n2lIlIMODvOqKNwAtYdoZH5feKt5P43i0=",
"Aza": "qmTKA257DLOrfhk5Zw8RyRmBSonmm6epbloT0P0ZWDc=",
// ... more peers
},
}
```
**Advantages:**
- Centralized configuration management
- JSON serialization support
- Type-safe access to configuration
- Easy to extend and maintain
### 3. **IP Address Validation**
**Bash Version:**
```bash
# Basic regex validation
validate_ip() {
local ip=$1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
return 0
else
return 1
fi
}
```
**Go Version:**
```go
func validateIP(ip string) error {
if ip == "" {
return fmt.Errorf("IP address cannot be empty")
}
// Check if it's in the expected range
if !ipRegex.MatchString(ip) {
return fmt.Errorf("IP should be in 10.8.0.x range for NextGen network")
}
// Validate IP format using net package
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return fmt.Errorf("invalid IP address format")
}
// Check for conflicts with existing peers
for peerName, peerIP := range map[string]string{
"Zion": "10.8.0.1",
"Cth": "10.8.0.10",
// ... more peers
} {
if ip == peerIP {
return fmt.Errorf("IP %s is already in use by %s", ip, peerName)
}
}
return nil
}
```
**Advantages:**
- Uses Go's `net` package for proper IP validation
- Checks for IP conflicts with existing peers
- More comprehensive validation
- Better error messages
### 4. **Key Generation**
**Bash Version:**
```bash
# Relies on external wg command
PRIVATE_KEY=$(wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | wg pubkey)
```
**Go Version:**
```go
func generateWireGuardKeys() (string, string, error) {
// Generate private key
privateKeyBytes := make([]byte, 32)
if _, err := rand.Read(privateKeyBytes); err != nil {
return "", "", err
}
// Ensure the key is valid for curve25519
privateKeyBytes[0] &= 248
privateKeyBytes[31] &= 127
privateKeyBytes[31] |= 64
// Generate public key using curve25519
var publicKeyBytes [32]byte
curve25519.ScalarBaseMult(&publicKeyBytes, (*[32]byte)(privateKeyBytes))
privateKey := base64.StdEncoding.EncodeToString(privateKeyBytes[:])
publicKey := base64.StdEncoding.EncodeToString(publicKeyBytes[:])
return privateKey, publicKey, nil
}
```
**Advantages:**
- No external dependencies for key generation
- Uses cryptographically secure random number generator
- Proper curve25519 key generation
- Better error handling
### 5. **File Operations**
**Bash Version:**
```bash
# Basic file operations
cat > "$CONFIG_FILE" << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = $IP_ADDRESS
EOF
```
**Go Version:**
```go
// Structured file operations with error handling
func generateConfig(hostname, ipAddress, privateKey, routingMode string) string {
var config strings.Builder
// Interface section
config.WriteString("[Interface]\n")
config.WriteString(fmt.Sprintf("Address = %s/24\n", ipAddress))
config.WriteString(fmt.Sprintf("PrivateKey = %s\n", privateKey))
// Add ListenPort for static servers
if port, exists := staticServers[ipAddress]; exists {
config.WriteString(fmt.Sprintf("ListenPort = %s\n", port))
}
// Add DNS for full tunnel mode
if routingMode == "full_tunnel" {
config.WriteString("DNS = 1.1.1.1, 8.8.8.8\n")
}
// Zion peer (always enabled)
config.WriteString("\n# Zion (central server)\n")
config.WriteString("[Peer]\n")
config.WriteString(fmt.Sprintf("PublicKey = %s\n", zionConfig.PublicKey))
// ... more configuration
return config.String()
}
```
**Advantages:**
- Uses `strings.Builder` for efficient string concatenation
- Structured configuration generation
- Better memory efficiency
- Type-safe operations
### 6. **User Input Handling**
**Bash Version:**
```bash
# Basic input with limited validation
read -p "Enter node name (e.g., aza, cth, galaxy): " NODE_NAME
if [ -z "$NODE_NAME" ]; then
print_error "Node name cannot be empty"
exit 1
fi
```
**Go Version:**
```go
func getUserInput(prompt string, validator func(string) error) string {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print(prompt)
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
if err := validator(input); err != nil {
printError(err.Error())
fmt.Print("Continue anyway? (y/N): ")
response, _ := reader.ReadString('\n')
response = strings.TrimSpace(strings.ToLower(response))
if response == "y" || response == "yes" {
return input
}
continue
}
return input
}
}
```
**Advantages:**
- Function-based validation
- Better error recovery
- Consistent input handling
- More flexible validation logic
### 7. **JSON Configuration Export**
**Go Version Only:**
```go
type WGConfig struct {
Hostname string `json:"hostname"`
IPAddress string `json:"ip_address"`
PrivateKey string `json:"private_key"`
PublicKey string `json:"public_key"`
RoutingMode string `json:"routing_mode"`
Generated string `json:"generated"`
ScriptVer string `json:"script_version"`
RunningRoot bool `json:"running_as_root"`
ZionPeer bool `json:"zion_peer_added"`
}
// Automatic JSON serialization
infoData, err := json.MarshalIndent(wgConfig, "", " ")
if err != nil {
printError(fmt.Sprintf("Failed to marshal config: %v", err))
os.Exit(1)
}
```
**Advantages:**
- Structured data export
- Easy integration with other tools
- Machine-readable configuration
- Better debugging and logging
## Performance Comparison
### Memory Usage
- **Bash**: Higher memory usage due to string operations and external commands
- **Go**: More efficient memory usage with `strings.Builder` and structured data
### Execution Speed
- **Bash**: Slower due to external command calls (`wg genkey`, `wg pubkey`)
- **Go**: Faster with native key generation and optimized string operations
### Dependencies
- **Bash**: Requires external tools (`wg`, `wg-quick`, `bash`)
- **Go**: Single binary with minimal runtime dependencies
## Maintainability
### Code Organization
- **Bash**: Functions scattered throughout, harder to maintain
- **Go**: Structured with clear separation of concerns
### Error Handling
- **Bash**: Basic error checking with exit codes
- **Go**: Comprehensive error handling with context
### Testing
- **Bash**: Difficult to unit test
- **Go**: Easy to unit test with structured functions
## Security Improvements
### Key Generation
- **Bash**: Relies on external `wg` command
- **Go**: Uses cryptographically secure random number generator
### Input Validation
- **Bash**: Basic regex validation
- **Go**: Comprehensive validation with multiple checks
### File Operations
- **Bash**: Basic file operations
- **Go**: Proper error handling and atomic operations
## Cross-Platform Compatibility
### Distribution
- **Bash**: Requires bash shell and external tools
- **Go**: Single binary that works on any platform
### Dependencies
- **Bash**: Platform-specific package managers
- **Go**: No external dependencies
## Conclusion
The Go implementation provides significant improvements over the bash version:
1. **Better Type Safety**: Compile-time error checking prevents runtime issues
2. **Improved Error Handling**: Structured error handling with context
3. **Enhanced Validation**: More comprehensive input validation
4. **Better Performance**: Native key generation and optimized operations
5. **Easier Maintenance**: Structured code with clear separation of concerns
6. **Cross-Platform**: Single binary with no external dependencies
7. **Better Security**: Cryptographically secure operations
8. **Structured Output**: JSON configuration export for integration
The Go version is more suitable for production use, especially in environments where reliability, security, and maintainability are important.