mirror of
https://github.com/go-i2p/go-i2p-testnet.git
synced 2025-06-16 05:44:41 -04:00
574 lines
16 KiB
Go
574 lines
16 KiB
Go
package i2pd
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"gopkg.in/ini.v1"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/client"
|
|
"go-i2p-testnet/lib/utils"
|
|
)
|
|
|
|
// I2PDConfig represents the complete i2pd configuration
|
|
type I2PDConfig struct {
|
|
// Global options (before any section)
|
|
TunnelsConf string `ini:"tunconf"`
|
|
TunnelsDir string `ini:"tunnelsdir"`
|
|
CertsDir string `ini:"certsdir"`
|
|
Pidfile string `ini:"pidfile"`
|
|
Log string `ini:"log"`
|
|
Logfile string `ini:"logfile"`
|
|
Loglevel string `ini:"loglevel"`
|
|
Logclftime bool `ini:"logclftime"`
|
|
Daemon bool `ini:"daemon"`
|
|
Family string `ini:"family"`
|
|
Ifname string `ini:"ifname"`
|
|
Ifname4 string `ini:"ifname4"`
|
|
Ifname6 string `ini:"ifname6"`
|
|
Address4 string `ini:"address4"`
|
|
Address6 string `ini:"address6"`
|
|
Host string `ini:"host"`
|
|
Port int `ini:"port"`
|
|
IPv4 bool `ini:"ipv4"`
|
|
IPv6 bool `ini:"ipv6"`
|
|
SSU bool `ini:"ssu"`
|
|
Bandwidth string `ini:"bandwidth"`
|
|
Share int `ini:"share"`
|
|
Notransit bool `ini:"notransit"`
|
|
Floodfill bool `ini:"floodfill"`
|
|
Service bool `ini:"service"`
|
|
Datadir string `ini:"datadir"`
|
|
Netid int `ini:"netid"`
|
|
Nat bool `ini:"nat"`
|
|
ReservedRange bool `ini:"reservedrange"`
|
|
// Sections
|
|
NTCP2 NTCP2Config `ini:"ntcp2"`
|
|
SSU2 SSU2Config `ini:"ssu2"`
|
|
HTTP HTTPConfig `ini:"http"`
|
|
HTTPProxy HTTPProxyConfig `ini:"httpproxy"`
|
|
SocksProxy SocksProxyConfig `ini:"socksproxy"`
|
|
SAM SAMConfig `ini:"sam"`
|
|
BOB BOBConfig `ini:"bob"`
|
|
I2CP I2CPConfig `ini:"i2cp"`
|
|
I2PControl I2PControlConfig `ini:"i2pcontrol"`
|
|
Cryptography CryptographyConfig `ini:"cryptography"`
|
|
UPnP UPnPConfig `ini:"upnp"`
|
|
Meshnets MeshnetsConfig `ini:"meshnets"`
|
|
Reseed ReseedConfig `ini:"reseed"`
|
|
Addressbook AddressbookConfig `ini:"addressbook"`
|
|
Limits LimitsConfig `ini:"limits"`
|
|
Trust TrustConfig `ini:"trust"`
|
|
Persist PersistConfig `ini:"persist"`
|
|
CPUExt CPUExtConfig `ini:"cpuext"`
|
|
Nettime NettimeConfig `ini:"nettime"`
|
|
//LocalAddressbook LocalAddressbookConfig `ini:"localaddressbook"`
|
|
//Windows WindowsConfig `ini:"windows"`
|
|
//Unix UnixConfig `ini:"unix"`
|
|
}
|
|
|
|
// NTCP2 Section
|
|
type NTCP2Config struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Published bool `ini:"published"`
|
|
Port int `ini:"port"`
|
|
}
|
|
|
|
// SSU2 Section
|
|
type SSU2Config struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Published bool `ini:"published"`
|
|
Port int `ini:"port"`
|
|
}
|
|
|
|
// HTTP Section
|
|
type HTTPConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
Webroot string `ini:"webroot"`
|
|
Auth bool `ini:"auth"`
|
|
User string `ini:"user"`
|
|
Pass string `ini:"pass"`
|
|
Lang string `ini:"lang"`
|
|
}
|
|
|
|
// HTTPProxy Section
|
|
type HTTPProxyConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
Keys string `ini:"keys"`
|
|
AddressHelper bool `ini:"addresshelper"`
|
|
Outproxy string `ini:"outproxy"`
|
|
SignatureType int `ini:"signaturetype"`
|
|
InboundQuantity int `ini:"inbound.quantity"`
|
|
OutboundLength int `ini:"outbound.length"`
|
|
OutboundQuantity int `ini:"outbound.quantity"`
|
|
OutboundLengthVariance int `ini:"outbound.lengthVariance"`
|
|
I2CPLeaseSetType int `ini:"i2cp.leaseSetType"`
|
|
I2CPLeaseSetEncType string `ini:"i2cp.leaseSetEncType"`
|
|
}
|
|
|
|
// SocksProxy Section
|
|
type SocksProxyConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
Keys string `ini:"keys"`
|
|
OutproxyEnabled bool `ini:"outproxy.enabled"`
|
|
Outproxy string `ini:"outproxy"`
|
|
OutproxyPort int `ini:"outproxyport"`
|
|
SignatureType int `ini:"signaturetype"`
|
|
InboundQuantity int `ini:"inbound.quantity"`
|
|
OutboundLength int `ini:"outbound.length"`
|
|
OutboundQuantity int `ini:"outbound.quantity"`
|
|
OutboundLengthVariance int `ini:"outbound.lengthVariance"`
|
|
I2CPLeaseSetType int `ini:"i2cp.leaseSetType"`
|
|
I2CPLeaseSetEncType string `ini:"i2cp.leaseSetEncType"`
|
|
}
|
|
|
|
// SAM Section
|
|
type SAMConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
SingleThread bool `ini:"singlethread"`
|
|
}
|
|
|
|
// BOB Section
|
|
type BOBConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
}
|
|
|
|
// I2CP Section
|
|
type I2CPConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
SingleThread bool `ini:"singlethread"`
|
|
}
|
|
|
|
// I2PControl Section
|
|
type I2PControlConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Address string `ini:"address"`
|
|
Port int `ini:"port"`
|
|
Password string `ini:"password"`
|
|
Cert string `ini:"cert"`
|
|
Key string `ini:"key"`
|
|
}
|
|
|
|
// Cryptography Section
|
|
type CryptographyConfig struct {
|
|
Precomputation PrecomputationConfig `ini:"precomputation"`
|
|
// Add other cryptographic options here
|
|
}
|
|
|
|
// Precomputation Section
|
|
type PrecomputationConfig struct {
|
|
ElGamal bool `ini:"elgamal"`
|
|
}
|
|
|
|
// UPnP Section
|
|
type UPnPConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Name string `ini:"name"`
|
|
}
|
|
|
|
// Meshnets Section
|
|
type MeshnetsConfig struct {
|
|
Yggdrasil bool `ini:"yggdrasil"`
|
|
YggAddress string `ini:"yggaddress"`
|
|
}
|
|
|
|
// Reseed Section
|
|
type ReseedConfig struct {
|
|
Verify bool `ini:"verify"`
|
|
URLs string `ini:"urls"`
|
|
YggURLs string `ini:"yggurls"`
|
|
File string `ini:"file"`
|
|
ZipFile string `ini:"zipfile"`
|
|
Proxy string `ini:"proxy"`
|
|
Threshold int `ini:"threshold"`
|
|
}
|
|
|
|
// Addressbook Section
|
|
type AddressbookConfig struct {
|
|
DefaultURL string `ini:"defaulturl"`
|
|
Subscriptions string `ini:"subscriptions"`
|
|
HostsFile string `ini:"hostsfile"`
|
|
}
|
|
|
|
// Limits Section
|
|
type LimitsConfig struct {
|
|
TransitTunnels int `ini:"transittunnels"`
|
|
OpenFiles int `ini:"openfiles"`
|
|
CoreSize int `ini:"coresize"`
|
|
Zombies float64 `ini:"zombies"`
|
|
}
|
|
|
|
// Trust Section
|
|
type TrustConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
Family string `ini:"family"`
|
|
Routers string `ini:"routers"`
|
|
Hidden bool `ini:"hidden"`
|
|
}
|
|
|
|
// TunnelConfig represents inbound or outbound tunnel configurations
|
|
type TunnelConfig struct {
|
|
Length int `ini:"length"`
|
|
Quantity int `ini:"quantity"`
|
|
}
|
|
|
|
// Persist Section
|
|
type PersistConfig struct {
|
|
Profiles bool `ini:"profiles"`
|
|
Addressbook bool `ini:"addressbook"`
|
|
}
|
|
|
|
// CPU Extensions Section
|
|
type CPUExtConfig struct {
|
|
AESNI bool `ini:"aesni"`
|
|
AVX bool `ini:"avx"`
|
|
Force bool `ini:"force"`
|
|
}
|
|
|
|
// Nettime Section
|
|
type NettimeConfig struct {
|
|
Enabled bool `ini:"enabled"`
|
|
NtpServers string `ini:"ntpservers"`
|
|
NtpSyncInterval int `ini:"ntpsyncinterval"`
|
|
}
|
|
|
|
func GenerateDefaultI2PDConfig() *I2PDConfig {
|
|
return &I2PDConfig{
|
|
// Global options (before any section)
|
|
TunnelsConf: "/var/lib/i2pd/tunnels.conf",
|
|
TunnelsDir: "/var/lib/i2pd/tunnels.d/",
|
|
CertsDir: "/var/lib/i2pd/certificates",
|
|
Pidfile: "/run/i2pd.pid",
|
|
Log: "stdout",
|
|
Logfile: "",
|
|
Loglevel: "debug",
|
|
Logclftime: false,
|
|
Daemon: false,
|
|
Family: "",
|
|
Ifname: "",
|
|
Ifname4: "",
|
|
Ifname6: "",
|
|
Address4: "",
|
|
Address6: "",
|
|
Host: "",
|
|
Port: 0, // Default is a random port
|
|
IPv4: true,
|
|
IPv6: true,
|
|
SSU: true,
|
|
Bandwidth: "L",
|
|
Share: 100,
|
|
Notransit: false,
|
|
Floodfill: true,
|
|
Service: false,
|
|
Datadir: "/var/lib/i2pd",
|
|
Netid: 2,
|
|
Nat: true,
|
|
|
|
// NTCP2 section
|
|
NTCP2: NTCP2Config{
|
|
Enabled: true,
|
|
Published: true,
|
|
Port: 0, // Uses global port option
|
|
},
|
|
|
|
// SSU2 section
|
|
SSU2: SSU2Config{
|
|
Enabled: true,
|
|
Published: true,
|
|
Port: 0, // Uses global port option or port + 1 if SSU is enabled
|
|
},
|
|
|
|
// HTTP section
|
|
HTTP: HTTPConfig{
|
|
Enabled: true,
|
|
Address: "127.0.0.1",
|
|
Port: 7070,
|
|
Webroot: "/",
|
|
Auth: false,
|
|
User: "",
|
|
Pass: "",
|
|
Lang: "english",
|
|
},
|
|
|
|
// HTTP Proxy section
|
|
HTTPProxy: HTTPProxyConfig{
|
|
Enabled: true,
|
|
Address: "127.0.0.1",
|
|
Port: 4444,
|
|
Keys: "",
|
|
AddressHelper: true,
|
|
Outproxy: "",
|
|
SignatureType: 7,
|
|
InboundQuantity: 5,
|
|
OutboundLength: 3,
|
|
OutboundQuantity: 5,
|
|
OutboundLengthVariance: 0,
|
|
I2CPLeaseSetType: 3,
|
|
I2CPLeaseSetEncType: "",
|
|
},
|
|
|
|
// SOCKS Proxy section
|
|
SocksProxy: SocksProxyConfig{
|
|
Enabled: true,
|
|
Address: "127.0.0.1",
|
|
Port: 4447,
|
|
Keys: "",
|
|
OutproxyEnabled: false,
|
|
Outproxy: "",
|
|
OutproxyPort: 0,
|
|
SignatureType: 7,
|
|
InboundQuantity: 5,
|
|
OutboundLength: 3,
|
|
OutboundQuantity: 5,
|
|
OutboundLengthVariance: 0,
|
|
I2CPLeaseSetType: 3,
|
|
I2CPLeaseSetEncType: "",
|
|
},
|
|
|
|
// SAM section
|
|
SAM: SAMConfig{
|
|
Enabled: true,
|
|
Address: "127.0.0.1",
|
|
Port: 7656,
|
|
SingleThread: true,
|
|
},
|
|
|
|
// BOB section
|
|
BOB: BOBConfig{
|
|
Enabled: false,
|
|
Address: "127.0.0.1",
|
|
Port: 2827,
|
|
},
|
|
|
|
// I2CP section
|
|
I2CP: I2CPConfig{
|
|
Enabled: false,
|
|
Address: "127.0.0.1",
|
|
Port: 7654,
|
|
SingleThread: true,
|
|
},
|
|
|
|
// I2PControl section
|
|
I2PControl: I2PControlConfig{
|
|
Enabled: false,
|
|
Address: "127.0.0.1",
|
|
Port: 7650,
|
|
Password: "itoopie",
|
|
Cert: "i2pcontrol.crt.pem",
|
|
Key: "i2pcontrol.key.pem",
|
|
},
|
|
|
|
// Cryptography section
|
|
Cryptography: CryptographyConfig{
|
|
Precomputation: PrecomputationConfig{
|
|
ElGamal: true,
|
|
},
|
|
// Initialize other cryptographic options as needed
|
|
},
|
|
|
|
// UPnP section
|
|
UPnP: UPnPConfig{
|
|
Enabled: false, // Disabled by default on non-Windows/Android platforms
|
|
Name: "I2Pd",
|
|
},
|
|
|
|
// Meshnets section
|
|
Meshnets: MeshnetsConfig{
|
|
Yggdrasil: false,
|
|
YggAddress: "",
|
|
},
|
|
|
|
// Reseed section
|
|
Reseed: ReseedConfig{
|
|
Verify: true,
|
|
URLs: "https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/",
|
|
YggURLs: "",
|
|
File: "",
|
|
ZipFile: "",
|
|
Proxy: "",
|
|
Threshold: 25,
|
|
},
|
|
|
|
// Addressbook section
|
|
Addressbook: AddressbookConfig{
|
|
DefaultURL: "http://reg.i2p/hosts.txt",
|
|
Subscriptions: "",
|
|
HostsFile: "hosts.txt",
|
|
},
|
|
|
|
// Limits section
|
|
Limits: LimitsConfig{
|
|
TransitTunnels: 10000, // As per default
|
|
OpenFiles: 0,
|
|
CoreSize: 0,
|
|
Zombies: 0.00,
|
|
},
|
|
|
|
// Trust section
|
|
Trust: TrustConfig{
|
|
Enabled: false,
|
|
Family: "",
|
|
Routers: "",
|
|
Hidden: false,
|
|
},
|
|
|
|
// Persist section
|
|
Persist: PersistConfig{
|
|
Profiles: true,
|
|
Addressbook: true,
|
|
},
|
|
|
|
// CPU Extensions section
|
|
CPUExt: CPUExtConfig{
|
|
AESNI: true,
|
|
AVX: true,
|
|
Force: false,
|
|
},
|
|
|
|
// Nettime section
|
|
Nettime: NettimeConfig{
|
|
Enabled: false,
|
|
NtpServers: "pool.ntp.org",
|
|
NtpSyncInterval: 72,
|
|
},
|
|
}
|
|
}
|
|
|
|
func GenerateRouterConfig(routerID int) (string, error) {
|
|
log.WithField("routerID", routerID).Debug("Starting i2pd router config generation")
|
|
|
|
// Initialize default configuration
|
|
config := GenerateDefaultI2PDConfig()
|
|
config.Netid = 5
|
|
config.ReservedRange = false
|
|
config.Nat = false
|
|
config.Floodfill = true
|
|
|
|
// Create an INI file from the struct
|
|
iniFile := ini.Empty()
|
|
err := iniFile.ReflectFrom(config)
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to reflect config struct to INI file")
|
|
return "", err
|
|
}
|
|
|
|
// Write INI file to a string
|
|
var buffer bytes.Buffer
|
|
_, err = iniFile.WriteTo(&buffer)
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to write INI file to buffer")
|
|
return "", err
|
|
}
|
|
|
|
configData := buffer.String()
|
|
|
|
log.WithFields(map[string]interface{}{
|
|
"routerID": routerID,
|
|
"config": configData,
|
|
}).Debug("i2pd router configuration generated successfully")
|
|
|
|
return configData, nil
|
|
}
|
|
|
|
func CopyConfigToVolume(cli *client.Client, ctx context.Context, volumeName string, configData string) error {
|
|
// Create a temporary container to copy data into the volume
|
|
log.WithField("volumeName", volumeName).Debug("Starting config copy to volume")
|
|
|
|
tempContainerConfig := &container.Config{
|
|
Image: "alpine",
|
|
Tty: false,
|
|
WorkingDir: "/var/lib/i2pd",
|
|
Cmd: []string{"sh", "-c", "mkdir -p /var/lib/i2pd && sleep 1d"},
|
|
}
|
|
|
|
hostConfig := &container.HostConfig{
|
|
Binds: []string{
|
|
fmt.Sprintf("%s:/var/lib/i2pd", volumeName),
|
|
},
|
|
}
|
|
|
|
log.WithFields(map[string]interface{}{
|
|
"image": tempContainerConfig.Image,
|
|
"volumeName": volumeName,
|
|
}).Debug("Creating temporary container")
|
|
|
|
resp, err := cli.ContainerCreate(ctx, tempContainerConfig, hostConfig, nil, nil, "")
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to create temporary container")
|
|
return fmt.Errorf("error creating temporary container: %v", err)
|
|
}
|
|
defer func() {
|
|
log.WithField("containerID", resp.ID).Debug("Removing temporary container")
|
|
removeOptions := container.RemoveOptions{Force: true}
|
|
err := cli.ContainerRemove(ctx, resp.ID, removeOptions)
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to remove temporary container")
|
|
}
|
|
}()
|
|
|
|
// Start the container
|
|
log.WithField("containerID", resp.ID).Debug("Starting temporary container")
|
|
startOptions := container.StartOptions{}
|
|
if err := cli.ContainerStart(ctx, resp.ID, startOptions); err != nil {
|
|
log.WithError(err).Error("Failed to start temporary container")
|
|
return fmt.Errorf("error starting temporary container: %v", err)
|
|
}
|
|
|
|
// Copy the configuration file into the container
|
|
log.Debug("Creating tar archive of config data")
|
|
tarReader, err := utils.CreateTarArchive("i2pd.conf", configData)
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to create tar archive")
|
|
return fmt.Errorf("error creating tar archive: %v", err)
|
|
}
|
|
|
|
// Copy to the container's volume-mounted directory
|
|
log.WithField("containerID", resp.ID).Debug("Copying config to container")
|
|
err = cli.CopyToContainer(ctx, resp.ID, "/var/lib/i2pd", tarReader, container.CopyToContainerOptions{})
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to copy config to container")
|
|
return fmt.Errorf("error copying to container: %v", err)
|
|
}
|
|
|
|
// Optionally, handle additional configuration files like local addressbook
|
|
/*
|
|
localAddrBookData := "your local addressbook content here"
|
|
tarReader, err = utils.CreateTarArchive("addressbook/local.csv", localAddrBookData)
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to create tar archive for local addressbook")
|
|
return fmt.Errorf("error creating tar archive for local addressbook: %v", err)
|
|
}
|
|
|
|
log.WithField("containerID", resp.ID).Debug("Copying local addressbook to container")
|
|
err = cli.CopyToContainer(ctx, resp.ID, "/var/lib/i2pd/addressbook", tarReader, container.CopyToContainerOptions{})
|
|
if err != nil {
|
|
log.WithError(err).Error("Failed to copy local addressbook to container")
|
|
return fmt.Errorf("error copying local addressbook to container: %v", err)
|
|
}
|
|
*/
|
|
|
|
// Stop the container
|
|
log.WithField("containerID", resp.ID).Debug("Stopping temporary container")
|
|
stopOptions := container.StopOptions{}
|
|
if err := cli.ContainerStop(ctx, resp.ID, stopOptions); err != nil {
|
|
log.WithError(err).Error("Failed to stop temporary container")
|
|
return fmt.Errorf("error stopping temporary container: %v", err)
|
|
}
|
|
|
|
log.Debug("Successfully copied config to volume")
|
|
return nil
|
|
}
|