This commit is contained in:
m5r 2024-07-21 22:59:32 +02:00
parent c3220327e1
commit 036793157b
Signed by: mokhtar
GPG Key ID: 1509B54946D08A95
10 changed files with 242 additions and 82 deletions

View File

@ -24,4 +24,5 @@ EXPOSE 443/tcp
USER root
CMD ["/local-ip/local-ip"]
# TODO: make these configurable too
CMD ["/local-ip/local-ip", "--domain", "local-ip.sh", "--email", "admin@local-ip.sh", "--nameservers", "ns1.local-ip.sh.,ns2.local-ip.sh."]

View File

@ -36,7 +36,8 @@ func (u *Account) GetPrivateKey() crypto.PrivateKey {
}
func LoadAccount() *Account {
jsonBytes, err := os.ReadFile(accountFilePath)
config := utils.GetConfig()
jsonBytes, err := os.ReadFile(config.AccountFilePath)
if err != nil {
if strings.Contains(err.Error(), "no such file or directory") {
RegisterAccount()
@ -51,7 +52,7 @@ func LoadAccount() *Account {
utils.Logger.Fatal().Err(err).Msg("Failed to unmarshal account JSON file")
}
privKey, err := os.ReadFile(keyFilePath)
privKey, err := os.ReadFile(config.KeyFilePath)
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Failed to read account's private key file")
}
@ -61,41 +62,42 @@ func LoadAccount() *Account {
}
func RegisterAccount() {
config := utils.GetConfig()
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Failed to generate account key")
}
account := &Account{
Email: email,
Email: config.Email,
key: privateKey,
}
config := lego.NewConfig(account)
config.CADirURL = caDirUrl
legoClient, err := lego.NewClient(config)
legoConfig := lego.NewConfig(account)
legoConfig.CADirURL = config.CADirURL
legoClient, err := lego.NewClient(legoConfig)
if err != nil {
utils.Logger.Fatal().Err(err).Str("CA Directory URL", config.CADirURL).Msg("Failed to initialize lego client")
utils.Logger.Fatal().Err(err).Str("CA Directory URL", legoConfig.CADirURL).Msg("Failed to initialize lego client")
}
reg, err := legoClient.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
utils.Logger.Fatal().Err(err).Str("CA Directory URL", config.CADirURL).Msg("Failed to register account to ACME server")
utils.Logger.Fatal().Err(err).Str("CA Directory URL", legoConfig.CADirURL).Msg("Failed to register account to ACME server")
}
if reg.Body.Status != "valid" {
utils.Logger.Fatal().Err(err).Str("CA Directory URL", config.CADirURL).Msgf("Registration failed with status %s", reg.Body.Status)
utils.Logger.Fatal().Err(err).Str("CA Directory URL", legoConfig.CADirURL).Msgf("Registration failed with status %s", reg.Body.Status)
}
utils.Logger.Debug().
Str("CA Directory URL", config.CADirURL).
Str("CA Directory URL", legoConfig.CADirURL).
Bool("TermsOfServiceAgreed", reg.Body.TermsOfServiceAgreed).
Msg("Successfully registered account to ACME server")
account.Registration = reg
os.MkdirAll(filepath.Dir(keyFilePath), os.ModePerm)
os.MkdirAll(filepath.Dir(config.KeyFilePath), os.ModePerm)
privKey := encode(privateKey)
err = os.WriteFile(keyFilePath, []byte(privKey), 0o644)
err = os.WriteFile(config.KeyFilePath, []byte(privKey), 0o644)
if err != nil {
utils.Logger.Fatal().Err(err).Str("path", keyFilePath).Msg("Failed to write account's private key file")
utils.Logger.Fatal().Err(err).Str("path", config.KeyFilePath).Msg("Failed to write account's private key file")
}
jsonBytes, err := json.MarshalIndent(account, "", "\t")
@ -103,10 +105,10 @@ func RegisterAccount() {
utils.Logger.Fatal().Err(err).Msg("Failed to marshal account JSON file")
}
os.MkdirAll(filepath.Dir(accountFilePath), os.ModePerm)
err = os.WriteFile(accountFilePath, jsonBytes, 0o600)
os.MkdirAll(filepath.Dir(config.AccountFilePath), os.ModePerm)
err = os.WriteFile(config.AccountFilePath, jsonBytes, 0o600)
if err != nil {
utils.Logger.Fatal().Err(err).Str("path", accountFilePath).Msg("Failed to write account's JSON file")
utils.Logger.Fatal().Err(err).Str("path", config.AccountFilePath).Msg("Failed to write account's JSON file")
}
}

View File

@ -27,14 +27,15 @@ func (c *certsClient) RequestCertificates() {
}
func (c *certsClient) requestCertificate(certType string) {
config := utils.GetConfig()
var lastCertificate *certificate.Resource
var domains []string
if certType == "wildcard" {
lastCertificate = c.lastWildcardCertificate
domains = []string{"*.local-ip.sh"}
domains = []string{fmt.Sprintf("*.%s", config.Domain)}
} else if certType == "root" {
lastCertificate = c.lastRootCertificate
domains = []string{"local-ip.sh"}
domains = []string{config.Domain}
} else {
utils.Logger.Fatal().Msgf("Unexpected certType %s. Only \"wildcard\" and \"root\" are supported", certType)
}
@ -119,9 +120,10 @@ func persistFiles(certificates *certificate.Resource, certType string) {
}
func NewCertsClient(xip *xip.Xip, user *Account) *certsClient {
config := lego.NewConfig(user)
config.CADirURL = caDirUrl
legoClient, err := lego.NewClient(config)
config := utils.GetConfig()
legoConfig := lego.NewConfig(user)
legoConfig.CADirURL = config.CADirURL
legoClient, err := lego.NewClient(legoConfig)
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Failed to initialize lego client")
}

View File

@ -1,21 +0,0 @@
package certs
import (
"fmt"
"net/url"
"github.com/go-acme/lego/v4/lego"
)
const (
email = "admin@local-ip.sh"
caDirUrl = lego.LEDirectoryProduction
// caDirUrl = lego.LEDirectoryStaging
)
var (
parsedCaDirUrl, _ = url.Parse(caDirUrl)
caDirHostname = parsedCaDirUrl.Hostname()
accountFilePath = fmt.Sprintf("./.lego/accounts/%s/%s/account.json", caDirHostname, email)
keyFilePath = fmt.Sprintf("./.lego/accounts/%s/%s/keys/%s.key", caDirHostname, email, email)
)

98
cmd/root.go Normal file
View File

@ -0,0 +1,98 @@
package cmd
import (
"fmt"
"net/url"
"strings"
"github.com/go-acme/lego/v4/lego"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"local-ip.sh/utils"
)
var command = &cobra.Command{
Use: "local-ip.sh",
PreRun: func(cmd *cobra.Command, args []string) {
staging, err := cmd.Flags().GetBool("staging")
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Unexpected error")
}
nameservers, err := cmd.Flags().GetString("nameservers")
if err != nil {
utils.Logger.Fatal().Err(err).Msg("Unexpected error")
}
viper.Set("NameServers", strings.Split(nameservers, ","))
var caDir string
if staging {
caDir = lego.LEDirectoryStaging
} else {
caDir = lego.LEDirectoryProduction
}
viper.Set("CADirURL", caDir)
parsedCaDirUrl, _ := url.Parse(caDir)
caDirHostname := parsedCaDirUrl.Hostname()
email := viper.GetString("Email")
viper.Set("AccountFilePath", fmt.Sprintf("./.lego/accounts/%s/%s/account.json", caDirHostname, email))
viper.Set("KeyFilePath", fmt.Sprintf("./.lego/accounts/%s/%s/keys/%s.key", caDirHostname, email, email))
utils.InitConfig()
},
Run: func(cmd *cobra.Command, args []string) {
c := utils.GetConfig()
fmt.Printf("%#v\n", c)
fmt.Println(c)
// n := xip.NewXip()
// go func() {
// account := certs.LoadAccount()
// certsClient := certs.NewCertsClient(n, account)
// time.Sleep(5 * time.Second)
// certsClient.RequestCertificates()
// for {
// // try to renew certificate every day
// time.Sleep(24 * time.Hour)
// certsClient.RequestCertificates()
// }
// }()
// go http.ServeHttp()
// n.StartServer()
},
}
func Execute() {
command.Flags().Uint("dns-port", 53, "Port for the DNS server")
viper.BindPFlag("dns-port", command.Flags().Lookup("dns-port"))
command.Flags().Uint("http-port", 80, "Port for the HTTP server")
viper.BindPFlag("http-port", command.Flags().Lookup("http-port"))
command.Flags().Uint("https-port", 443, "Port for the HTTPS server")
viper.BindPFlag("https-port", command.Flags().Lookup("https-port"))
command.Flags().Bool("staging", false, "Enable to use the Let's Encrypt staging environment to obtain certificates")
viper.BindPFlag("staging", command.Flags().Lookup("staging"))
command.Flags().String("domain", "", "Root domain (required)")
command.MarkFlagRequired("domain")
viper.BindPFlag("domain", command.Flags().Lookup("domain"))
command.Flags().String("email", "", "ACME account email address (required)")
command.MarkFlagRequired("email")
viper.BindPFlag("email", command.Flags().Lookup("email"))
command.Flags().String("nameservers", "", "List of nameservers separated by commas")
command.MarkFlagRequired("nameservers")
if err := command.Execute(); err != nil {
utils.Logger.Fatal().Err(err).Msg("")
}
}

26
go.mod
View File

@ -6,18 +6,38 @@ require (
github.com/go-acme/lego/v4 v4.10.1
github.com/miekg/dns v1.1.57
github.com/rs/zerolog v1.33.0
golang.org/x/net v0.17.0
golang.org/x/net v0.23.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)
require (
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/crypto v0.14.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

57
go.sum
View File

@ -1,9 +1,13 @@
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-acme/lego/v4 v4.10.1 h1:MiJvoBXNdmAwEK/SImyhwZ8ZL4IR0jtWDD1wST+N138=
github.com/go-acme/lego/v4 v4.10.1/go.mod h1:EMbf0Jmqwv94nJ5WL9qWnSXIBZnvsS9gNypansHGc6U=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
@ -11,6 +15,12 @@ github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxF
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@ -19,25 +29,68 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -50,10 +103,14 @@ golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

30
main.go
View File

@ -1,35 +1,9 @@
package main
import (
"flag"
"time"
"local-ip.sh/certs"
"local-ip.sh/http"
"local-ip.sh/xip"
"local-ip.sh/cmd"
)
func main() {
port := flag.Int("port", 53, "port the DNS server should bind to")
flag.Parse()
n := xip.NewXip(*port)
go func() {
account := certs.LoadAccount()
certsClient := certs.NewCertsClient(n, account)
time.Sleep(5 * time.Second)
certsClient.RequestCertificates()
for {
// try to renew certificate every day
time.Sleep(24 * time.Hour)
certsClient.RequestCertificates()
}
}()
go http.ServeHttp()
n.StartServer()
cmd.Execute()
}

29
utils/config.go Normal file
View File

@ -0,0 +1,29 @@
package utils
import (
"github.com/spf13/viper"
)
type config struct {
DnsPort uint `mapstructure:"dns-port"`
HttpPort uint `mapstructure:"http-port"`
HttpsPort uint `mapstructure:"https-port"`
Domain string
Email string
NameServers []string
CADirURL string
AccountFilePath string
KeyFilePath string
}
var conf = &config{}
func InitConfig() *config {
viper.Unmarshal(conf)
return conf
}
func GetConfig() *config {
return conf
}

View File

@ -26,16 +26,12 @@ type HardcodedRecord struct {
SRV *dns.SRV
}
const (
zone = "local-ip.sh."
nameservers = "ns1.local-ip.sh.,ns2.local-ip.sh."
)
var (
flyRegion = os.Getenv("FLY_REGION")
dottedIpV4Regex = regexp.MustCompile(`(?:^|(?:[\w\d])+\.)(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})($|[.-])`)
dashedIpV4Regex = regexp.MustCompile(`(?:^|(?:[\w\d])+\.)(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\-?\b){4})($|[.-])`)
hardcodedRecords = map[string]HardcodedRecord{
// TODO: maybe --nameservers ns1.local-ip.sh.=137.66.40.11,ns2.local-ip.sh.=137.66.40.12
"ns.local-ip.sh.": {
// record holding ip addresses of ns1 and ns2
A: []net.IP{
@ -424,18 +420,20 @@ func (xip *Xip) StartServer() {
utils.Logger.Info().Str("dns_address", xip.server.Addr).Msg("DNS server listening")
}
func NewXip(port int) (xip *Xip) {
func NewXip() (xip *Xip) {
config := utils.GetConfig()
xip = &Xip{}
for _, ns := range strings.Split(nameservers, ",") {
for _, ns := range config.NameServers {
xip.nameServers = append(xip.nameServers, &dns.NS{Ns: ns})
}
xip.server = dns.Server{
Addr: fmt.Sprintf(":%d", port),
Addr: fmt.Sprintf(":%d", config.DnsPort),
Net: "udp",
}
zone := fmt.Sprintf("%s.", config.Domain)
dns.HandleFunc(zone, xip.handleDnsRequest)
return xip