diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md index a4cae3d..748062f 100644 --- a/docs/DEVELOPER.md +++ b/docs/DEVELOPER.md @@ -60,18 +60,7 @@ dig @$DNS_SERVER_IP txt ip.sslip.io +short | tr -d '"' echo 127.0.0.1 dig @$DNS_SERVER_IP txt version.status.sslip.io +short | grep $VERSION echo "\"$VERSION\"" -dig @$DNS_SERVER_IP my-key.k-v.io txt +short # returns nothing echo " ===" # separator because the results are too similar -dig @$DNS_SERVER_IP put.MyValue.my-key.k-v.io txt +short -echo "\"MyValue\"" -echo " ===" # separator because the results are too similar -dig @$DNS_SERVER_IP MY-KEY.k-v.io txt +short -echo "\"MyValue\"" -echo " ===" # separator because the results are too similar -dig @$DNS_SERVER_IP delete.my-key.k-v.io txt +short -echo -echo " ===" # separator because the results are too similar -dig @$DNS_SERVER_IP my-key.k-v.io txt +short # returns nothing dig @$DNS_SERVER_IP 1.0.0.127.in-addr.arpa ptr +short echo "127-0-0-1.sslip.io." dig @$DNS_SERVER_IP metrics.status.sslip.io txt +short | grep '"Queries: ' diff --git a/k8s/document_root_k-v.io/index.html b/k8s/document_root_k-v.io/index.html index 345d442..28462c5 100644 --- a/k8s/document_root_k-v.io/index.html +++ b/k8s/document_root_k-v.io/index.html @@ -36,6 +36,8 @@ k-v.io + k-v.io is under construction. I've dismantled the DNS-backed key-value store—no one was using it. Stay + tuned. + diff --git a/src/sslip.io-dns-server/default.json b/src/sslip.io-dns-server/default.json index b04ad82..e086ac4 100644 --- a/src/sslip.io-dns-server/default.json +++ b/src/sslip.io-dns-server/default.json @@ -21,14 +21,6 @@ "TXTSslipIoSPF" ] }, - "k-v.io.": { - "A": [ - "104.155.144.4" - ] - }, - "_acme-challenge.k-v.io.": { - "TXT": [] - }, "ns.sslip.io.": { "A": [ "52.0.56.137", diff --git a/src/sslip.io-dns-server/go.mod b/src/sslip.io-dns-server/go.mod index ab7e56d..86fd0e8 100644 --- a/src/sslip.io-dns-server/go.mod +++ b/src/sslip.io-dns-server/go.mod @@ -1,33 +1,22 @@ module xip -go 1.19 +go 1.20 require ( github.com/onsi/ginkgo/v2 v2.8.4 github.com/onsi/gomega v1.27.2 - go.etcd.io/etcd/client/v3 v3.5.7 golang.org/x/net v0.7.0 ) require ( - github.com/coreos/go-semver v0.3.1 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect - go.etcd.io/etcd/api/v3 v3.5.7 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - go.uber.org/zap v1.24.0 // indirect + github.com/stretchr/testify v1.8.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect golang.org/x/tools v0.6.0 // indirect - google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514 // indirect - google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/sslip.io-dns-server/go.sum b/src/sslip.io-dns-server/go.sum index 9130d5c..0d852ce 100644 --- a/src/sslip.io-dns-server/go.sum +++ b/src/sslip.io-dns-server/go.sum @@ -1,8 +1,3 @@ -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= @@ -10,87 +5,40 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/onsi/ginkgo/v2 v2.8.4 h1:gf5mIQ8cLFieruNLAdgijHF1PYfLphKm2dxxcUtcqK0= github.com/onsi/ginkgo/v2 v2.8.4/go.mod h1:427dEDQZkDKsBvCjc2A/ZPefhKxsTTrsQegMlayL730= github.com/onsi/gomega v1.27.2 h1:SKU0CXeKE/WVgIV1T61kSa3+IRE8Ekrv9rdXDwwTqnY= github.com/onsi/gomega v1.27.2/go.mod h1:5mR3phAHpkAVIDkHEUBY6HGVsU+cpcEscrGPB4oPlZI= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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/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/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= -go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= -go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= -go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= -go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= -go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -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= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514 h1:rtNKfB++wz5mtDY2t5C8TXlU5y52ojSu7tZo0z7u8eQ= -google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/sslip.io-dns-server/integration_metrics_test.go b/src/sslip.io-dns-server/integration_metrics_test.go index cb77cd5..132fb18 100644 --- a/src/sslip.io-dns-server/integration_metrics_test.go +++ b/src/sslip.io-dns-server/integration_metrics_test.go @@ -123,30 +123,6 @@ var _ = Describe("IntegrationMetrics", func() { actualMetrics = digAndGetMetrics("@localhost version.status.sslip.io txt +short -p "+strconv.Itoa(port), port) Expect(expectedMetrics.MostlyEquals(actualMetrics)).To(BeTrue()) - // TXT put.value.key.k-v.io updates .Queries, .AnsweredQueries, .AnsweredTXTPutKvQueries - expectedMetrics.Queries++ - expectedMetrics.AnsweredQueries++ - expectedMetrics.AnsweredTXTPutKvQueries++ - expectedMetrics = bumpExpectedToAccountForMetricsQuery(expectedMetrics) - actualMetrics = digAndGetMetrics("@localhost put.value.key.k-v.io txt +short -p "+strconv.Itoa(port), port) - Expect(expectedMetrics.MostlyEquals(actualMetrics)).To(BeTrue()) - - // TXT key.k-v.io updates .Queries, .AnsweredQueries, .AnsweredTXTGetKvQueries - expectedMetrics.Queries++ - expectedMetrics.AnsweredQueries++ - expectedMetrics.AnsweredTXTGetKvQueries++ - expectedMetrics = bumpExpectedToAccountForMetricsQuery(expectedMetrics) - actualMetrics = digAndGetMetrics("@localhost key.k-v.io txt +short -p "+strconv.Itoa(port), port) - Expect(expectedMetrics.MostlyEquals(actualMetrics)).To(BeTrue()) - - // TXT delete.key.k-v.io updates .Queries, .AnsweredTXTDelKvQueries - // It doesn't count as an "answered" query because it returns no record - expectedMetrics.Queries++ - expectedMetrics.AnsweredTXTDelKvQueries++ - expectedMetrics = bumpExpectedToAccountForMetricsQuery(expectedMetrics) - actualMetrics = digAndGetMetrics("@localhost delete.key.k-v.io txt +short -p "+strconv.Itoa(port), port) - Expect(expectedMetrics.MostlyEquals(actualMetrics)).To(BeTrue()) - // PTR version.sslip.io updates .Queries, .AnsweredQueries, .AnsweredPTRQueriesIPv4 expectedMetrics.Queries++ expectedMetrics.AnsweredQueries++ @@ -203,7 +179,6 @@ func getMetrics(port int) (m xip.Metrics) { var junk string _, err = fmt.Sscanf(string(stdout), "\"Uptime: %d\"\n"+ - "\"KV Store: %s\n"+ // %s "swallows" the double-quote at the end "\"Blocklist: %s %s %s\n"+ "\"Queries: %d (%s\n"+ // %s "swallows" the `/s"` at the end "\"Answered Queries: %d (%s\n"+ // %s "swallows" the `/s"` at the end @@ -211,12 +186,10 @@ func getMetrics(port int) (m xip.Metrics) { "\"AAAA: %d\"\n"+ "\"TXT Source: %d\"\n"+ "\"TXT Version: %d\"\n"+ - "\"TXT KV GET/PUT/DEL: %d/%d/%d\"\n"+ "\"PTR IPv4/IPv6: %d/%d\"\n"+ "\"NS DNS-01: %d\"\n"+ "\"Blocked: %d\"\n", &uptime, - &junk, &junk, &junk, &junk, &m.Queries, &junk, &m.AnsweredQueries, &junk, @@ -224,7 +197,6 @@ func getMetrics(port int) (m xip.Metrics) { &m.AnsweredAAAAQueries, &m.AnsweredTXTSrcIPQueries, &m.AnsweredTXTVersionQueries, - &m.AnsweredTXTGetKvQueries, &m.AnsweredTXTPutKvQueries, &m.AnsweredTXTDelKvQueries, &m.AnsweredPTRQueriesIPv4, &m.AnsweredPTRQueriesIPv6, &m.AnsweredNSDNS01ChallengeQueries, &m.AnsweredBlockedQueries, diff --git a/src/sslip.io-dns-server/integration_test.go b/src/sslip.io-dns-server/integration_test.go index f4ca2ba..62c2d6c 100644 --- a/src/sslip.io-dns-server/integration_test.go +++ b/src/sslip.io-dns-server/integration_test.go @@ -58,10 +58,6 @@ var _ = Describe("sslip.io-dns-server", func() { Eventually(string(digSession.Out.Contents())).Should(MatchRegexp(digResults)) Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(serverLogMessage)) }, - Entry("A (customized) for k-v.io", - "@localhost k-v.io +short", - `\A104.155.144.4\n\z`, - `TypeA k-v.io. \? 104.155.144.4\n`), Entry("A (customized) for sslip.io", "@localhost sslip.io +short", `\A78.46.204.247\n\z`, @@ -131,26 +127,6 @@ var _ = Describe("sslip.io-dns-server", func() { "@127.0.0.1 example.com txt +short", `\A\z`, `TypeTXT example.com. \? nil, SOA example.com. briancunnie.gmail.com. 2022112600 900 900 1800 180\n`), - Entry(`getting a non-existent value: TXT for non-existent.k-v.io"`, - "@127.0.0.1 non-existent.k-v.io txt +short", - `\A\z`, - `TypeTXT non-existent.k-v.io. \? nil, SOA non-existent.k-v.io. briancunnie.gmail.com. 2022112600 900 900 1800 180\n`), - Entry(`putting a value: TXT for put.MyValue.MY-KEY.k-v.io"`, - "@127.0.0.1 put.MyValue.MY-KEY.k-v.io txt +short", - `"MyValue"`, - `TypeTXT put.MyValue.MY-KEY.k-v.io. \? \["MyValue"\]`), - Entry(`deleting a value: TXT for delete.my-key.k-v.io"`, - "@127.0.0.1 delete.my-key.k-v.io txt +short", - `\A\z`, - `TypeTXT delete.my-key.k-v.io. \? nil, SOA delete.my-key.k-v.io. briancunnie.gmail.com. 2022112600 900 900 1800 180\n`), - Entry(`setting a TXT for _acme-challenge.k-v.io appears to work (spoiler: it doesn't)'"`, - "@127.0.0.1 put.sneaky-boy._acme-challenge.k-v.io txt +short", - `sneaky-boy`, - `TypeTXT put.sneaky-boy._acme-challenge.k-v.io. \? \["sneaky-boy"\]`), - Entry(`get a TXT for _acme-challenge.k-v.io is blocked to foil Let's Encrypt ACME DNS-01 challenge"`, - "@127.0.0.1 _acme-challenge.k-v.io txt +short", - `Please don't try to procure a k-v.io cert via DNS-01 challenge`, - `TypeTXT _acme-challenge.k-v.io. \? \["Please don't try to procure a k-v.io cert via DNS-01 challenge"\]`), Entry(`get a PTR for 1.0.168.192.in-addr.arpa returns 192-168-0-1.sslip.io`, "@127.0.0.1 1.0.168.192.in-addr.arpa ptr +short", `\A192-168-0-1.sslip.io.\n\z`, @@ -267,79 +243,6 @@ var _ = Describe("sslip.io-dns-server", func() { Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT sslip.io. \? \["protonmail-verification=ce0ca3f5010aa7a2cf8bcc693778338ffde73e26"\], \["v=spf1 include:_spf.protonmail.ch mx ~all"\]\n`)) }) }) - When(`a TXT record for a host under the "k-v.io" domain is queried`, func() { - It(`the PUT has a three-minute TTL`, func() { - digArgs = "@localhost put.a.a.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(digSession.Out.Contents())).Should(MatchRegexp(`put.a.a.k-v.io. 180 IN TXT "a"`)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT put.a.a.k-v.io. \? \["a"\]`)) - }) - It(`the GET has a three-minute TTL`, func() { - // create (PUT) the key - digArgs = "@localhost put.a.b.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - // retrieve (GET) the key - digArgs = "@localhost b.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(digSession.Out.Contents()), 3).Should(MatchRegexp(`b.k-v.io. 180 IN TXT "a"`)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT b.k-v.io. \? \["a"\]`)) - }) - It(`the DELETE returns no records so that value cached in downstream DNS servers expires more quickly`, func() { - // create (PUT) the key - digArgs = "@localhost put.a.c.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - // DELETE the key - digArgs = "@localhost delete.c.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT delete.c.k-v.io. \? nil, SOA delete.c.k-v.io. briancunnie.gmail.com. 2022112600 900 900 1800 180`)) - }) - It(`the DELETE on a non-existent key behaves the same as the DELETE on an existing key`, func() { - // DELETE the key (make sure it's gone) - digArgs = "@localhost delete.d.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - // DELETE again to test the non-existent behavior - digArgs = "@localhost delete.d.k-v.io txt -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT delete.d.k-v.io. \? nil, SOA delete.d.k-v.io. briancunnie.gmail.com. 2022112600 900 900 1800 180`)) - }) - It(`setting a TXT for _acme-challenge.subdomain-key.k-v.io doesn't expose DNS-01 vulnerability`, func() { - // set (PUT) the key - digArgs = "@localhost put.baffled-boy._acme-challenge.subdomain-key.k-v.io txt +short -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - // GET the key - digArgs = "@localhost get.subdomain-key.k-v.io txt +short -p " + strconv.Itoa(port) - digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) - digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) - Expect(err).ToNot(HaveOccurred()) - Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(digSession.Out.Contents()), 3).Should(MatchRegexp(`"baffled-boy._acme-challenge"`)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT get.subdomain-key.k-v.io. \? \["baffled-boy._acme-challenge"\]`)) - }) - }) When(`a record for an "_acme-challenge" domain is queried`, func() { When(`it's an NS record`, func() { It(`returns the NS record of the query with the "_acme-challenge." stripped`, func() { diff --git a/src/sslip.io-dns-server/main.go b/src/sslip.io-dns-server/main.go index 5c16cd1..192034e 100644 --- a/src/sslip.io-dns-server/main.go +++ b/src/sslip.io-dns-server/main.go @@ -15,13 +15,11 @@ import ( func main() { var wg sync.WaitGroup - var etcdEndpoint = flag.String("etcdHost", "localhost:2379", "etcd client endpoint; falls back to builtin key-value store if unable to connect") var blocklistURL = flag.String("blocklistURL", "https://raw.githubusercontent.com/cunnie/sslip.io/main/etc/blocklist.txt", `URL containing a list of "forbidden" names/CIDRs`) var nameservers = flag.String("nameservers", "ns-aws.sslip.io.,ns-azure.sslip.io.,ns-gce.sslip.io.", "comma-separated list of nameservers") var addresses = flag.String("addresses", "sslip.io=78.46.204.247,"+ "sslip.io=2a01:4f8:c17:b8f::2,"+ - "k-v.io=104.155.144.4,"+ "ns.sslip.io=52.0.56.137,"+ "ns.sslip.io=52.187.42.158,"+ "ns.sslip.io=104.155.144.4,"+ @@ -34,10 +32,10 @@ func main() { var quiet = flag.Bool("quiet", false, "suppresses logging of each DNS response") flag.Parse() log.Printf("%s version %s starting", os.Args[0], xip.VersionSemantic) - log.Printf("etcd endpoint: %s, blocklist URL: %s, name servers: %s, bind port: %d, quiet: %t", - *etcdEndpoint, *blocklistURL, *nameservers, *bindPort, *quiet) + log.Printf("blocklist URL: %s, name servers: %s, bind port: %d, quiet: %t", + *blocklistURL, *nameservers, *bindPort, *quiet) - x, logmessages := xip.NewXip(*etcdEndpoint, *blocklistURL, strings.Split(*nameservers, ","), strings.Split(*addresses, ",")) + x, logmessages := xip.NewXip(*blocklistURL, strings.Split(*nameservers, ","), strings.Split(*addresses, ",")) for _, logmessage := range logmessages { log.Println(logmessage) } diff --git a/src/sslip.io-dns-server/xip/xip.go b/src/sslip.io-dns-server/xip/xip.go index d19a0b8..35ec35e 100644 --- a/src/sslip.io-dns-server/xip/xip.go +++ b/src/sslip.io-dns-server/xip/xip.go @@ -5,7 +5,6 @@ package xip import ( "bufio" - "context" "errors" "fmt" "io" @@ -14,29 +13,18 @@ import ( "net/http" "net/netip" "os" - "reflect" "regexp" "strconv" "strings" "time" - clientv3 "go.etcd.io/etcd/client/v3" "golang.org/x/net/dns/dnsmessage" ) //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate -//counterfeiter:generate . V3client -type V3client interface { - Get(context.Context, string, ...clientv3.OpOption) (*clientv3.GetResponse, error) - Put(context.Context, string, string, ...clientv3.OpOption) (*clientv3.PutResponse, error) - Delete(context.Context, string, ...clientv3.OpOption) (*clientv3.DeleteResponse, error) - Close() error -} - // Xip is meant to be a singleton that holds global state for the DNS server type Xip struct { - Etcd V3client // etcd client for `k-v.io` DnsAmplificationAttackDelay chan struct{} // for throttling metrics.status.sslip.io Metrics Metrics // DNS server metrics BlocklistStrings []string // list of blacklisted strings that shouldn't appear in public hostnames @@ -54,9 +42,6 @@ type Metrics struct { AnsweredAAAAQueries int AnsweredTXTSrcIPQueries int AnsweredTXTVersionQueries int - AnsweredTXTGetKvQueries int - AnsweredTXTPutKvQueries int - AnsweredTXTDelKvQueries int AnsweredNSDNS01ChallengeQueries int AnsweredBlockedQueries int AnsweredPTRQueriesIPv4 int @@ -88,12 +73,6 @@ type DomainCustomization struct { // DNS hostnames are technically case-insensitive type DomainCustomizations map[string]DomainCustomization -// KvCustomizations is a lookup table for custom TXT records -// e.g. KvCustomizations["my-key"] = []dnsmessage.TXTResource{ TXT: { "my-value" } } -// The key should NOT include ".k-v.io." -// It's used when there's no etcd server running -type KvCustomizations map[string][]dnsmessage.TXTResource - // There's nothing like global variables to make my heart pound with joy. // Some of these are global because they are, in essence, constants which // I don't want to waste time recreating with every function call. @@ -105,7 +84,6 @@ var ( ipv4ReverseRE = regexp.MustCompile(`^(.*)\.in-addr\.arpa\.$`) ipv6ReverseRE = regexp.MustCompile(`^(([[:xdigit:]]\.){32})ip6\.arpa\.`) dns01ChallengeRE = regexp.MustCompile(`(?i)_acme-challenge\.`) // (?i) → non-capturing case insensitive - kvRE = regexp.MustCompile(`\.k-v\.io\.$`) mbox, _ = dnsmessage.NewName("briancunnie.gmail.com.") mx1, _ = dnsmessage.NewName("mail.protonmail.ch.") @@ -120,16 +98,7 @@ var ( MetricsBufferSize = 200 // big enough to run our tests, and small enough to prevent DNS amplification attacks - // etcdContextTimeout — the duration (context) that we wait for etcd to get back to us - // - etcd queries on the nameserver take as long as 482 milliseconds on the "slow" server, 247 on the "fast" - // - round-trip time from my house in San Francisco to ns-azure in Singapore is 190 milliseconds - // - time between queries with `dig` on my macOS Monterey is 5000 milliseconds, three queries before giving up - // - quadruple the headroom for queries 4 x 482 = 1928, should still leave enough room to get answer back - // within the 5000 milliseconds - etcdContextTimeout = 1928 * time.Millisecond - - TxtKvCustomizations = KvCustomizations{} - Customizations = DomainCustomizations{ + Customizations = DomainCustomizations{ "sslip.io.": { MX: []dnsmessage.MXResource{ { @@ -143,12 +112,6 @@ var ( }, TXT: TXTSslipIoSPF, }, - // don't let people procure *.k-v.io TLS certs via ACME DNS-01 challenge - "_acme-challenge.k-v.io.": { - TXT: func(_ *Xip, _ net.IP) ([]dnsmessage.TXTResource, error) { - return []dnsmessage.TXTResource{{TXT: []string{"Please don't try to procure a k-v.io cert via DNS-01 challenge"}}}, nil - }, - }, // nameserver addresses; we get queries for those every once in a while // CNAMEs for sslip.io for DKIM signing "protonmail._domainkey.sslip.io.": { @@ -201,19 +164,8 @@ type Response struct { } // NewXip follows convention for constructors: https://go.dev/doc/effective_go#allocation_new -func NewXip(etcdEndpoint, blocklistURL string, nameservers []string, addresses []string) (x *Xip, logmessages []string) { - var err error +func NewXip(blocklistURL string, nameservers []string, addresses []string) (x *Xip, logmessages []string) { x = &Xip{Metrics: Metrics{Start: time.Now()}} - // connect to `etcd`; if there's an error, set etcdCli to `nil` and that to - // determine whether to use a local key-value store instead - x.Etcd, err = clientv3New(etcdEndpoint) - if err != nil { - logmessages = append(logmessages, fmt.Sprintf("failed to connect to etcd at %s, using local key-value store instead: %s", etcdEndpoint, err.Error())) - } else { - logmessages = append(logmessages, fmt.Sprintf("Successfully connected to etcd at %s", etcdEndpoint)) - } - // don't `defer etcdCli.Close()`: "The Client has internal state (watchers and leases), so - // Clients should be reused instead of created as needed" // Download the blocklist logmessages = append(logmessages, x.downloadBlockList(blocklistURL)) @@ -819,7 +771,7 @@ func (x *Xip) NSResources(fqdnString string) []dnsmessage.NSResource { return x.NameServers } -// TXTResources returns TXT records from Customizations or KvCustomizations +// TXTResources returns TXT records from Customizations func (x *Xip) TXTResources(fqdn string, ip net.IP) ([]dnsmessage.TXTResource, error) { if domain, ok := Customizations[strings.ToLower(fqdn)]; ok { // Customizations[strings.ToLower(fqdn)] returns a _function_, @@ -828,9 +780,6 @@ func (x *Xip) TXTResources(fqdn string, ip net.IP) ([]dnsmessage.TXTResource, er return domain.TXT(x, ip) } } - if kvRE.MatchString(fqdn) { - return x.kvTXTResources(fqdn) - } return nil, nil } @@ -938,11 +887,6 @@ func TXTMetrics(x *Xip, _ net.IP) (txtResources []dnsmessage.TXTResource, err er var metrics []string uptime := time.Since(x.Metrics.Start) metrics = append(metrics, fmt.Sprintf("Uptime: %.0f", uptime.Seconds())) - keyValueStore := "etcd" - if x.isEtcdNil() { - keyValueStore = "builtin" - } - metrics = append(metrics, "KV Store: "+keyValueStore) metrics = append(metrics, fmt.Sprintf("Blocklist: %s %d,%d", x.BlocklistUpdated.Format("2006-01-02 15:04:05-07"), len(x.BlocklistStrings), @@ -953,7 +897,6 @@ func TXTMetrics(x *Xip, _ net.IP) (txtResources []dnsmessage.TXTResource, err er metrics = append(metrics, fmt.Sprintf("AAAA: %d", x.Metrics.AnsweredAAAAQueries)) metrics = append(metrics, fmt.Sprintf("TXT Source: %d", x.Metrics.AnsweredTXTSrcIPQueries)) metrics = append(metrics, fmt.Sprintf("TXT Version: %d", x.Metrics.AnsweredTXTVersionQueries)) - metrics = append(metrics, fmt.Sprintf("TXT KV GET/PUT/DEL: %d/%d/%d", x.Metrics.AnsweredTXTGetKvQueries, x.Metrics.AnsweredTXTPutKvQueries, x.Metrics.AnsweredTXTDelKvQueries)) metrics = append(metrics, fmt.Sprintf("PTR IPv4/IPv6: %d/%d", x.Metrics.AnsweredPTRQueriesIPv4, x.Metrics.AnsweredPTRQueriesIPv6)) metrics = append(metrics, fmt.Sprintf("NS DNS-01: %d", x.Metrics.AnsweredNSDNS01ChallengeQueries)) metrics = append(metrics, fmt.Sprintf("Blocked: %d", x.Metrics.AnsweredBlockedQueries)) @@ -963,106 +906,6 @@ func TXTMetrics(x *Xip, _ net.IP) (txtResources []dnsmessage.TXTResource, err er return txtResources, nil } -// when TXT for "k-v.io" is queried, return the key-value pair -func (x *Xip) kvTXTResources(fqdn string) ([]dnsmessage.TXTResource, error) { - // "labels" => official RFC 1035 term - // k-v.io. => ["k-v", "io"] are labels - var ( - verb string // i.e. "get", "put", "delete" - key string // e.g. "my-key" as in "my-key.k-v.io" - value string // e.g. "my-value" as in "put.my-value.my-key.k-v.io" - ) - labels := strings.Split(fqdn, ".") - labels = labels[:len(labels)-3] // strip ".k-v.io" - // key is always present, always first subdomain of "k-v.io" - key = strings.ToLower(labels[len(labels)-1]) - switch { - case len(labels) == 1: - verb = "get" // default action if only key, not verb, is not present - case len(labels) == 2: - verb = strings.ToLower(labels[0]) // verb, if present, is leftmost, "put.value.key.k-v.io" - case len(labels) > 2: - verb = strings.ToLower(labels[0]) - // concatenate multiple labels to create value, especially useful for version numbers - value = strings.Join(labels[1:len(labels)-1], ".") // e.g. "put.94.0.2.firefox-version.k-v.io" - } - // prepare to query etcd: - switch verb { - case "get": - return x.getKv(key) - case "put": - if len(labels) == 2 { - return []dnsmessage.TXTResource{{[]string{"422: missing a value: put.value.key.k-v.io"}}}, nil - } - return x.putKv(key, value) - case "delete": - return x.deleteKv(key) - } - return []dnsmessage.TXTResource{{[]string{"422: valid verbs are get, put, delete"}}}, nil -} - -func (x *Xip) getKv(key string) ([]dnsmessage.TXTResource, error) { - if x.isEtcdNil() { - if txtRecord, ok := TxtKvCustomizations[key]; ok { - x.Metrics.AnsweredTXTGetKvQueries++ - return txtRecord, nil - } - return nil, nil - } - ctx, cancel := context.WithTimeout(context.Background(), etcdContextTimeout) - defer cancel() - resp, err := x.Etcd.Get(ctx, key) - if err != nil { - return nil, fmt.Errorf(`couldn't GET "%s": %w`, key, err) - } - if len(resp.Kvs) > 0 { - x.Metrics.AnsweredTXTGetKvQueries++ - return []dnsmessage.TXTResource{{[]string{string(resp.Kvs[0].Value)}}}, nil - } - return []dnsmessage.TXTResource{}, nil -} - -func (x *Xip) putKv(key, value string) ([]dnsmessage.TXTResource, error) { - if len(value) > 63 { // too-long TXT records can be used in DNS amplification attacks; Truncate! - value = value[:63] - } - if x.isEtcdNil() { - TxtKvCustomizations[key] = []dnsmessage.TXTResource{ - { - []string{value}, - }, - } - x.Metrics.AnsweredTXTPutKvQueries++ - return TxtKvCustomizations[key], nil - } - ctx, cancel := context.WithTimeout(context.Background(), etcdContextTimeout) - defer cancel() - _, err := x.Etcd.Put(ctx, key, value) - if err != nil { - return nil, fmt.Errorf("couldn't PUT (%s: %s): %w", key, value, err) - } - x.Metrics.AnsweredTXTPutKvQueries++ - return []dnsmessage.TXTResource{{[]string{value}}}, nil -} - -func (x *Xip) deleteKv(key string) ([]dnsmessage.TXTResource, error) { - if x.isEtcdNil() { - if _, ok := TxtKvCustomizations[key]; ok { - x.Metrics.AnsweredTXTDelKvQueries++ - delete(TxtKvCustomizations, key) - } - return nil, nil - } - ctx, cancel := context.WithTimeout(context.Background(), etcdContextTimeout) - defer cancel() - _, err := x.Etcd.Delete(ctx, key) - if err != nil { - return nil, fmt.Errorf("couldn't DELETE (key %s): %w", key, err) - } - x.Metrics.AnsweredTXTDelKvQueries++ - return nil, nil -} - // soaLogMessage returns an easy-to-read string for logging SOA Answers/Authorities func soaLogMessage(soaResource dnsmessage.SOAResource) string { return soaResource.NS.String() + " " + @@ -1082,9 +925,6 @@ func (a Metrics) MostlyEquals(b Metrics) bool { a.AnsweredAAAAQueries == b.AnsweredAAAAQueries && a.AnsweredTXTSrcIPQueries == b.AnsweredTXTSrcIPQueries && a.AnsweredTXTVersionQueries == b.AnsweredTXTVersionQueries && - a.AnsweredTXTGetKvQueries == b.AnsweredTXTGetKvQueries && - a.AnsweredTXTPutKvQueries == b.AnsweredTXTPutKvQueries && - a.AnsweredTXTDelKvQueries == b.AnsweredTXTDelKvQueries && a.AnsweredPTRQueriesIPv4 == b.AnsweredPTRQueriesIPv4 && a.AnsweredPTRQueriesIPv6 == b.AnsweredPTRQueriesIPv6 && a.AnsweredNSDNS01ChallengeQueries == b.AnsweredNSDNS01ChallengeQueries && @@ -1161,15 +1001,6 @@ func ReadBlocklist(blocklist io.Reader) (stringBlocklists []string, cidrBlocklis return stringBlocklists, cidrBlocklists, nil } -func (x *Xip) isEtcdNil() bool { - // comparing interfaces to nil are tricky: interfaces contain both a type - // and a value, and although the value is nil the type isn't, so we need the following - if x.Etcd == nil || reflect.ValueOf(x.Etcd).IsNil() { - return true - } - return false -} - func (x *Xip) blocklist(hostname string) bool { aResources := NameToA(hostname) aaaaResources := NameToAAAA(hostname) @@ -1322,25 +1153,3 @@ func (x *Xip) nameToAAAAwithBlocklist(q dnsmessage.Question, response Response, } return response, logMessage + strings.Join(logMessages, ", "), nil } - -// clientv3New attempts to connect to local etcd and retrieve a key to make -// sure the connection works. If for any reason it fails it returns nil + -// error -func clientv3New(etcdEndpoint string) (*clientv3.Client, error) { - etcdEndpoints := []string{etcdEndpoint} - etcdCli, err := clientv3.New(clientv3.Config{ - Endpoints: etcdEndpoints, - DialTimeout: 250 * time.Millisecond, - }) - if err != nil { - return nil, err - } - // Let's do a query to determine if etcd is really, truly there - ctx, cancel := context.WithTimeout(context.Background(), etcdContextTimeout) - defer cancel() - _, err = etcdCli.Get(ctx, "some-silly-key, doesn't matter if it exists") - if err != nil { - return nil, err - } - return etcdCli, nil -} diff --git a/src/sslip.io-dns-server/xip/xip_test.go b/src/sslip.io-dns-server/xip/xip_test.go index 097f9f6..1d60d0d 100644 --- a/src/sslip.io-dns-server/xip/xip_test.go +++ b/src/sslip.io-dns-server/xip/xip_test.go @@ -5,12 +5,10 @@ import ( "math/rand" "net" "strings" - "time" "xip/xip" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - clientv3 "go.etcd.io/etcd/client/v3" "golang.org/x/net/dns/dnsmessage" ) @@ -81,7 +79,7 @@ var _ = Describe("Xip", func() { Describe("NSResources()", func() { When("we use the default nameservers", func() { - var x, _ = xip.NewXip("localhost:2379", "file:///", []string{"ns-aws.sslip.io.", "ns-azure.sslip.io.", "ns-gce.sslip.io."}, []string{}) + var x, _ = xip.NewXip("file:///", []string{"ns-aws.sslip.io.", "ns-azure.sslip.io.", "ns-gce.sslip.io."}, []string{}) It("returns the name servers", func() { randomDomain := random8ByteString() + ".com." ns := x.NSResources(randomDomain) @@ -113,7 +111,7 @@ var _ = Describe("Xip", func() { }) }) When("we override the default nameservers", func() { - var x, _ = xip.NewXip("localhost:2379", "file:///", []string{"mickey", "minn.ie.", "goo.fy"}, []string{}) + var x, _ = xip.NewXip("file:///", []string{"mickey", "minn.ie.", "goo.fy"}, []string{}) It("returns the configured servers", func() { randomDomain := random8ByteString() + ".com." ns := x.NSResources(randomDomain) @@ -178,69 +176,6 @@ var _ = Describe("Xip", func() { Expect(len(txts)).To(Equal(0)) }) }) - When(`the domain "k-v.io is queried"`, Ordered, func() { - txtTests := func() { - DescribeTable(`the domain "k-v.io" is queried for TXT records`, - func(fqdn string, txts []string) { - txtResources, err := x.TXTResources(fqdn, nil) - Expect(err).ToNot(HaveOccurred()) - Expect(len(txtResources)).To(Equal(len(txts))) - for i, txtResource := range txtResources { - Expect(len(txtResource.TXT)).To(Equal(1)) // each TXT record has 1 & only 1 string - Expect(txtResource.TXT[0]).To(Equal(txts[i])) - } - }, - // simple tests: get, put, delete with single label value - Entry("no arguments → empty array", "k-v.io.", []string{}), - Entry("putting a value → that value", "PUT.MyValue.my-key.k-v.io.", []string{"MyValue"}), - Entry("getting that value → that value", "my-key.k-v.io.", []string{"MyValue"}), - Entry("getting that value with an UPPERCASE key → that value", "MY-KEY.k-v.io.", []string{"MyValue"}), - Entry("explicitly getting that value → that value", "GeT.my-key.k-v.io.", []string{"MyValue"}), - Entry("deleting that value → empty array", "DelETe.my-key.k-v.io.", []string{}), - Entry("getting that deleted value → empty array", "my-key.k-v.io.", []string{}), - // errors - Entry("getting a non-existent key → empty array", "nonexistent.k-v.io.", []string{}), - Entry("putting but skipping the value → error txt", "put.my-key.k-v.io.", []string{"422: missing a value: put.value.key.k-v.io"}), - Entry("deleting a non-existent key → silently succeeds", "delete.non-existent.k-v.io.", []string{}), - Entry("using a garbage verb → error txt", "post.my-key.k-v.io.", []string{"422: valid verbs are get, put, delete"}), - // others - Entry("putting a multi-label value", "put.96.0.4664.55.chrome-version.k-v.io.", []string{"96.0.4664.55"}), - Entry("putting a super-long multi-label value to use in a DNS amplification attack gets truncated to 63 characters", - "put"+ - ".IReturnedAndSawUnderTheSunThatTheRaceIsNotToTheSwiftNotThe"+ - ".BattleToTheStrongNeitherYetBreadToTheWiseNorYetRichesToMenOf"+ - ".amplify.k-v.io.", - []string{"IReturnedAndSawUnderTheSunThatTheRaceIsNotToTheSwiftNotThe.Batt"}, - ), - ) - - } - When("there's no etcd, just local, in-memory key-value", func() { - txtTests() - }) - etcdURI := "localhost:2379" - // make sure there's an etcd listening before we run our tests - conn, err := net.DialTimeout("tcp", etcdURI, 250*time.Millisecond) - if err == nil { - err = conn.Close() - Expect(err).ToNot(HaveOccurred()) - When(`etcd is backing the kv store`, func() { - BeforeEach(func() { - etcdCli, err := clientv3.New(clientv3.Config{ - Endpoints: []string{etcdURI}, - DialTimeout: 250 * time.Millisecond, - }) - Expect(err).ToNot(HaveOccurred()) - x.Etcd = etcdCli - }) - AfterEach(func() { - err = x.Etcd.Close() - Expect(err).ToNot(HaveOccurred()) - }) - txtTests() - }) - } - }) }) Describe("NameToA()", func() {
k-v.io is under construction. I've dismantled the DNS-backed key-value store—no one was using it. Stay + tuned.