Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ebc2393d96 | ||
|
0de7bd35f3 | ||
|
6a10139785 | ||
|
4a163fde36 | ||
|
7e32f63216 | ||
|
507b16fbd0 | ||
|
46b3388b83 | ||
|
d0033bc409 | ||
|
df90e5947e | ||
|
a288e99bda | ||
|
2b23be6f74 | ||
|
d0fc2ff8e6 | ||
|
b51cca5347 | ||
|
54be47f844 | ||
|
32e9a42493 | ||
|
fce8a51ed8 | ||
|
6adda5f544 | ||
|
4ad4578103 | ||
|
4b0f083f72 | ||
|
a1d3313299 | ||
|
5bbc9b922c | ||
|
4201a704f8 | ||
|
be529a50d1 | ||
|
f7c594af5a | ||
|
17a8ed4414 | ||
|
5b4fd41ffa | ||
|
9f31f76d02 | ||
|
1919aed4e6 | ||
|
73c604e9c4 | ||
|
38781e39fe | ||
|
92a819e45a | ||
|
6610db601b | ||
|
166705fc60 | ||
|
d006a19738 | ||
|
117923cdcb | ||
|
aef2ae70d5 | ||
|
ce2342cb8f | ||
|
015fcaf0d2 | ||
|
c56ec05ae7 | ||
|
cc15ec8496 | ||
|
5b6b33139b |
12
Makefile
12
Makefile
@ -2,13 +2,19 @@ GOARCH := $(GOARCH)
|
|||||||
GOOS := $(GOOS)
|
GOOS := $(GOOS)
|
||||||
FLAGS := -ldflags "-s -w"
|
FLAGS := -ldflags "-s -w"
|
||||||
|
|
||||||
all:
|
all: meshnamed whoami
|
||||||
|
|
||||||
|
meshnamed:
|
||||||
GOARCH=$$GOARCH GOOS=$$GOOS go build $(FLAGS) ./cmd/meshnamed
|
GOARCH=$$GOARCH GOOS=$$GOOS go build $(FLAGS) ./cmd/meshnamed
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
GOARCH=$$GOARCH GOOS=$$GOOS go build $(FLAGS) ./cmd/whoami
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) meshnamed meshnamed.exe
|
$(RM) meshnamed meshnamed.exe whoami whoami.exe
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test pkg/meshname/*_test.go
|
go test pkg/meshname/*_test.go
|
||||||
|
|
||||||
.PHONY: all clean test
|
.PHONY: all meshnamed whoami clean test
|
||||||
|
|
||||||
|
82
README.md
82
README.md
@ -1,5 +1,7 @@
|
|||||||
# meshname
|
# meshname
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/zhoreeq/meshname/master/img/logo-medium.png">
|
||||||
|
|
||||||
A universal naming system for all IPv6-based mesh networks, including CJDNS and Yggdrasil.
|
A universal naming system for all IPv6-based mesh networks, including CJDNS and Yggdrasil.
|
||||||
Implements the [Meshname protocol](https://github.com/zhoreeq/meshname/blob/master/protocol.md).
|
Implements the [Meshname protocol](https://github.com/zhoreeq/meshname/blob/master/protocol.md).
|
||||||
|
|
||||||
@ -11,85 +13,17 @@ Implements the [Meshname protocol](https://github.com/zhoreeq/meshname/blob/mast
|
|||||||
- Q: *Meshname domains are ugly.*
|
- Q: *Meshname domains are ugly.*
|
||||||
- A: Yes, if you want decentralization, you either have ugly names or a blockchain. Meshname has ugly names, but it works at least!
|
- A: Yes, if you want decentralization, you either have ugly names or a blockchain. Meshname has ugly names, but it works at least!
|
||||||
|
|
||||||
## How to install and use
|
## How to use meshname domains?
|
||||||
|
|
||||||
Minimum go version 1.12 is required.
|
Use a full-featured DNS server with the meshname protocol support, i.e. [PopuraDNS](https://github.com/popura-network/PopuraDNS).
|
||||||
|
|
||||||
1) Get the source code and compile
|
For a standalone .meshname stub resolver see `USAGE.md`
|
||||||
```
|
|
||||||
git clone https://github.com/zhoreeq/meshname.git
|
|
||||||
cd meshname
|
|
||||||
make
|
|
||||||
```
|
|
||||||
2) Generate the default config for your host
|
|
||||||
```
|
|
||||||
./meshnamed -genconf 200:6fc8:9220:f400:5cc2:305a:4ac6:967e -subdomain meshname | tee /tmp/meshnamed.conf
|
|
||||||
```
|
|
||||||
3) Run the daemon
|
|
||||||
```
|
|
||||||
./meshnamed -useconffile /tmp/meshnamed.conf
|
|
||||||
```
|
|
||||||
4) Optionally, set configuration flags
|
|
||||||
```
|
|
||||||
./meshnamed -listenaddr [::1]:53535 -debug -useconffile /tmp/meshnamed.conf
|
|
||||||
```
|
|
||||||
5) See the list of all configuration flags
|
|
||||||
```
|
|
||||||
./meshnamed -help
|
|
||||||
```
|
|
||||||
Add custom DNS records to the configuration file and restart the daemon to apply settings.
|
|
||||||
A DNS record can be of any valid string form parsed by [miekg/dns#NewRR](https://godoc.org/github.com/miekg/dns#NewRR) function (see example configuration file below).
|
|
||||||
|
|
||||||
## systemd unit
|
## Alternative implementations
|
||||||
|
|
||||||
Look for `meshnamed.service` in the source directory for a systemd unit file.
|
[Mario DNS](https://notabug.org/acetone/mario-dns) by acetone, a C++ implementation with a web interface.
|
||||||
|
|
||||||
## Example configuration file
|
[Ruby gem](https://rubygems.org/gems/meshname) by marek22k, [source](https://github.com/marek22k/meshname).
|
||||||
|
|
||||||
In this example, meshnamed is configured as authoritative server for two domain zones:
|
|
||||||
|
|
||||||
{
|
|
||||||
"aiag7sesed2aaxgcgbnevruwpy": [
|
|
||||||
"aiag7sesed2aaxgcgbnevruwpy.meshname. AAAA 200:6fc8:9220:f400:5cc2:305a:4ac6:967e",
|
|
||||||
"_xmpp-client._tcp.aiag7sesed2aaxgcgbnevruwpy.meshname. SRV 5 0 5222 xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname",
|
|
||||||
"_xmpp-server._tcp.aiag7sesed2aaxgcgbnevruwpy.meshname. SRV 5 0 5269 xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname",
|
|
||||||
"xmpp.aiag7sesed2aaxgcgbnevruwpy.meshname. AAAA 300:6fc8:9220:f400::1",
|
|
||||||
"forum.aiag7sesed2aaxgcgbnevruwpy.meshname. CNAME amag7sesed2aaaaaaaaaaaaaau.meshname."
|
|
||||||
],
|
|
||||||
"amag7sesed2aaaaaaaaaaaaaau": [
|
|
||||||
"amag7sesed2aaaaaaaaaaaaaau.meshname. AAAA 300:6fc8:9220:f400::5"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
## Configure dnsmasq as a primary DNS resolver with "meshname." support
|
|
||||||
|
|
||||||
`/etc/dnsmasq.conf`
|
|
||||||
|
|
||||||
port=53
|
|
||||||
domain-needed
|
|
||||||
bogus-priv
|
|
||||||
server=/meshname/::1#53535
|
|
||||||
server=8.8.8.8
|
|
||||||
|
|
||||||
## Using meshnamed as a standalone DNS server
|
|
||||||
|
|
||||||
Set the flag to listen on all interfaces and a standard DNS server port
|
|
||||||
|
|
||||||
./meshnamed -listenaddr [::]:53 -useconffile /tmp/meshnamed.conf
|
|
||||||
|
|
||||||
Run as root and allow incoming connections to port 53/UDP in firewall settings.
|
|
||||||
|
|
||||||
## Custom top level domains (TLD) and subnet filtering
|
|
||||||
|
|
||||||
meshnamed can be configured to resolve custom TLDs.
|
|
||||||
To run meshnamed for TLD `.newmesh` with addresses in `fd00::/8`
|
|
||||||
set a flag `-networks newmesh=fd00::/8`.
|
|
||||||
|
|
||||||
By default, in addition to `.meshname` it also resolves `.ygg` for IPv6 addresses in
|
|
||||||
`200::/7` subnet and `.cjd` for `fc00::/8`.
|
|
||||||
|
|
||||||
Requests are filtered by subnet validation. Request is ignored if a decoded
|
|
||||||
IPv6 address doesn't match the specified subnet for a TLD.
|
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
58
USAGE.md
Normal file
58
USAGE.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# How to install and use
|
||||||
|
|
||||||
|
Minimum go version 1.12 is required.
|
||||||
|
|
||||||
|
1) Get the source code and compile
|
||||||
|
```
|
||||||
|
git clone https://github.com/zhoreeq/meshname.git
|
||||||
|
cd meshname
|
||||||
|
make
|
||||||
|
```
|
||||||
|
2) Run the daemon
|
||||||
|
```
|
||||||
|
./meshnamed
|
||||||
|
```
|
||||||
|
3) Optionally, set configuration flags
|
||||||
|
```
|
||||||
|
./meshnamed -listenaddr [::1]:53535 -debug
|
||||||
|
```
|
||||||
|
4) See the list of all available flags
|
||||||
|
```
|
||||||
|
./meshnamed -help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get meshname subdomain from an IPv6 address
|
||||||
|
|
||||||
|
```
|
||||||
|
./meshnamed -getname 200:f8b1:f974:967f:dd32:145d:1cc0:3679
|
||||||
|
aiaprmpzoslh7xjscrorzqbwpe
|
||||||
|
```
|
||||||
|
|
||||||
|
Use this subdomain with a .meshname TLD to configure DNS records
|
||||||
|
on your authoritative server, (i.e. dnsmasq, bind or PopuraDNS).
|
||||||
|
|
||||||
|
## systemd unit
|
||||||
|
|
||||||
|
Look for `meshnamed.service` in the source directory for a systemd unit file.
|
||||||
|
|
||||||
|
## Configure dnsmasq as a primary DNS resolver with "meshname." support
|
||||||
|
|
||||||
|
`/etc/dnsmasq.conf`
|
||||||
|
|
||||||
|
port=53
|
||||||
|
domain-needed
|
||||||
|
bogus-priv
|
||||||
|
server=/meshname/::1#53535
|
||||||
|
server=8.8.8.8
|
||||||
|
|
||||||
|
## Custom top level domains (TLD) and subnet filtering
|
||||||
|
|
||||||
|
meshnamed can be configured to resolve custom TLDs.
|
||||||
|
To run meshnamed for TLD `.newmesh` with addresses in `fd00::/8`
|
||||||
|
set a flag `-networks newmesh=fd00::/8`.
|
||||||
|
|
||||||
|
By default, in addition to `.meshname` it also resolves `.ygg` for IPv6 addresses in
|
||||||
|
`200::/7` subnet and `.cjd` for `fc00::/8`.
|
||||||
|
|
||||||
|
Requests are filtered by subnet validation. Request is ignored if a decoded
|
||||||
|
IPv6 address doesn't match the specified subnet for a TLD.
|
@ -28,26 +28,22 @@ func parseNetworks(networksconf string) (map[string]*net.IPNet, error) {
|
|||||||
return networks, nil
|
return networks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(s *meshname.MeshnameServer, confPath string) error {
|
|
||||||
dnsRecords, err := meshname.ParseConfigFile(confPath)
|
|
||||||
if err == nil {
|
|
||||||
s.ConfigureDNSRecords(dnsRecords)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
genconf, subdomain, useconffile, listenAddr, networksconf string
|
listenAddr, networksconf string
|
||||||
debug, allowRemote bool
|
meshipNetworksconf string
|
||||||
|
getName, getIP string
|
||||||
|
acmePort string
|
||||||
|
debug, noMeshIP bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(&genconf, "genconf", "", "generate a new config for IP address")
|
|
||||||
flag.StringVar(&subdomain, "subdomain", "meshname.", "subdomain used to generate config")
|
|
||||||
flag.StringVar(&useconffile, "useconffile", "", "run daemon with a config file")
|
|
||||||
flag.StringVar(&listenAddr, "listenaddr", "[::1]:53535", "address to listen on")
|
flag.StringVar(&listenAddr, "listenaddr", "[::1]:53535", "address to listen on")
|
||||||
flag.StringVar(&networksconf, "networks", "ygg=200::/7,cjd=fc00::/8,meshname=::/0", "TLD=subnet list separated by comma")
|
flag.StringVar(&networksconf, "networks", "ygg=200::/7,cjd=fc00::/8,meshname=::/0,popura=::/0", "TLD=subnet list separated by comma")
|
||||||
flag.BoolVar(&allowRemote, "allowremote", false, "allow remote queries from any IP address")
|
flag.StringVar(&meshipNetworksconf, "meshipnetworks", "meship=::/0", "TLD=subnet list separated by comma")
|
||||||
|
flag.BoolVar(&noMeshIP, "nomeship", false, "disable .meship resolver")
|
||||||
|
flag.StringVar(&getName, "getname", "", "convert IPv6 address to a name")
|
||||||
|
flag.StringVar(&getIP, "getip", "", "convert a name to IPv6 address")
|
||||||
|
flag.StringVar(&acmePort, "acmeport", "53536", "try alternative port for acme challenges")
|
||||||
flag.BoolVar(&debug, "debug", false, "enable debug logging")
|
flag.BoolVar(&debug, "debug", false, "enable debug logging")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,26 +59,30 @@ func main() {
|
|||||||
logger.EnableLevel("debug")
|
logger.EnableLevel("debug")
|
||||||
}
|
}
|
||||||
|
|
||||||
if genconf != "" {
|
if getName != "" {
|
||||||
if conf, err := meshname.GenConf(genconf, subdomain); err == nil {
|
ip := net.ParseIP(getName)
|
||||||
fmt.Println(conf)
|
if ip == nil {
|
||||||
} else {
|
logger.Fatal("Invalid IP address")
|
||||||
logger.Errorln(err)
|
|
||||||
}
|
}
|
||||||
|
subDomain := meshname.DomainFromIP(&ip)
|
||||||
|
fmt.Println(subDomain)
|
||||||
|
return
|
||||||
|
} else if getIP != "" {
|
||||||
|
ip, err := meshname.IPFromDomain(&getIP)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(ip)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
networks, err := parseNetworks(networksconf)
|
networks, err := parseNetworks(networksconf)
|
||||||
|
meshipNetworks, err := parseNetworks(meshipNetworksconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalln(err)
|
logger.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := meshname.New(logger, listenAddr, networks, allowRemote)
|
s := meshname.New(logger, listenAddr, networks, meshipNetworks, !noMeshIP, acmePort)
|
||||||
if useconffile != "" {
|
|
||||||
if err := loadConfig(s, useconffile); err != nil {
|
|
||||||
logger.Fatalln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.Start(); err != nil {
|
if err := s.Start(); err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
@ -98,12 +98,6 @@ func main() {
|
|||||||
select {
|
select {
|
||||||
case <-c:
|
case <-c:
|
||||||
return
|
return
|
||||||
case <-r:
|
|
||||||
if useconffile != "" {
|
|
||||||
if err := loadConfig(s, useconffile); err != nil {
|
|
||||||
logger.Errorln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
69
cmd/whoami/main.go
Normal file
69
cmd/whoami/main.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net"
|
||||||
|
"encoding/base32"
|
||||||
|
"strings"
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// define tld
|
||||||
|
var tld = flag.String("tld", "mesh.cat", "The top level domain for our network")
|
||||||
|
|
||||||
|
// domainFromIP derives a meshname subdomain for the authoritative DNS server address
|
||||||
|
func domainFromIP(target net.IP) string {
|
||||||
|
host := strings.ToLower(base32.StdEncoding.EncodeToString(target)[0:26])
|
||||||
|
domain := host + "." + *tld
|
||||||
|
return domain
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle HTTP requests
|
||||||
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// parse query parameters
|
||||||
|
params := r.URL.Query()
|
||||||
|
ipParam := params.Get("ip")
|
||||||
|
// check if the "ip" query parameter is set to "true"
|
||||||
|
showIP := ipParam == "true"
|
||||||
|
// get client's ip address
|
||||||
|
ip, port, err := net.SplitHostPort(r.RemoteAddr)
|
||||||
|
_, _ = port, err
|
||||||
|
// check if we're behind a reverse proxy
|
||||||
|
xForwardedFor := r.Header.Get("X-Forwarded-For")
|
||||||
|
if xForwardedFor != "" {
|
||||||
|
ip = xForwardedFor
|
||||||
|
}
|
||||||
|
parsedIP := net.ParseIP(ip)
|
||||||
|
// return domain for IPv6 only
|
||||||
|
if parsedIP.To4() == nil {
|
||||||
|
if (showIP) {
|
||||||
|
w.Write([]byte(ip + "\n"))
|
||||||
|
log.Println(ip)
|
||||||
|
} else {
|
||||||
|
domain := domainFromIP(parsedIP)
|
||||||
|
w.Write([]byte(domain + "\n"))
|
||||||
|
log.Println(domain)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// set the response status code to 422
|
||||||
|
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||||
|
w.Write([]byte("ipv4 not supported\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// define path
|
||||||
|
http.HandleFunc("/", handler)
|
||||||
|
// define ip address
|
||||||
|
address := flag.String("address", "[::0]", "The interface address to listen on")
|
||||||
|
// define port
|
||||||
|
port := flag.String("port", "8008", "The port to listen on")
|
||||||
|
// parse the command-line arguments
|
||||||
|
flag.Parse()
|
||||||
|
// construct listening address
|
||||||
|
listenAddr := *address + ":" + *port
|
||||||
|
print("Listening on address: ", listenAddr, "\n")
|
||||||
|
// start server
|
||||||
|
http.ListenAndServe(listenAddr, nil)
|
||||||
|
}
|
69
contrib/gentoo/meshnamed-0.1.0.ebuild
Normal file
69
contrib/gentoo/meshnamed-0.1.0.ebuild
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
|
||||||
|
EAPI="7"
|
||||||
|
inherit go-module
|
||||||
|
|
||||||
|
DESCRIPTION="Meshname, a universal naming system for all IPv6-based mesh networks, including CJDNS and Yggdrasil"
|
||||||
|
HOMEPAGE="https://github.com/zhoreeq/meshname"
|
||||||
|
|
||||||
|
EGO_SUM=(
|
||||||
|
"github.com/gologme/log v1.2.0"
|
||||||
|
"github.com/gologme/log v1.2.0/go.mod"
|
||||||
|
"github.com/miekg/dns v1.1.27"
|
||||||
|
"github.com/miekg/dns v1.1.27/go.mod"
|
||||||
|
"golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod"
|
||||||
|
"golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550"
|
||||||
|
"golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod"
|
||||||
|
"golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod"
|
||||||
|
"golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod"
|
||||||
|
"golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod"
|
||||||
|
"golang.org/x/net v0.0.0-20190923162816-aa69164e4478"
|
||||||
|
"golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod"
|
||||||
|
"golang.org/x/sync v0.0.0-20190423024810-112230192c58"
|
||||||
|
"golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod"
|
||||||
|
"golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod"
|
||||||
|
"golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod"
|
||||||
|
"golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe"
|
||||||
|
"golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod"
|
||||||
|
"golang.org/x/text v0.3.0/go.mod"
|
||||||
|
"golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod"
|
||||||
|
"golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod"
|
||||||
|
)
|
||||||
|
go-module_set_globals
|
||||||
|
|
||||||
|
if [[ ${PV} != *9999* ]]; then
|
||||||
|
SRC_URI="https://github.com/zhoreeq/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
|
||||||
|
KEYWORDS="amd64 ~amd64 x86 ~x86"
|
||||||
|
else
|
||||||
|
EGIT_REPO_URI="https://github.com/zhoreeq/${PN}.git"
|
||||||
|
KEYWORDS="amd64 x86"
|
||||||
|
fi
|
||||||
|
SRC_URI+="${EGO_SUM_SRC_URI}"
|
||||||
|
|
||||||
|
LICENSE="MIT"
|
||||||
|
SLOT="0"
|
||||||
|
IUSE="systemd"
|
||||||
|
|
||||||
|
DEPEND=">dev-lang/go-1.12"
|
||||||
|
|
||||||
|
src_install() {
|
||||||
|
echo ""
|
||||||
|
exeinto /usr/bin
|
||||||
|
doexe meshnamed
|
||||||
|
dodoc README.md protocol.md
|
||||||
|
|
||||||
|
if use systemd ; then
|
||||||
|
systemd_newunit "${PN}d.service" ${PN}d.service
|
||||||
|
else
|
||||||
|
newinitd "${FILESDIR}/${PN}d.initd" ${PN}d
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg_postinst() {
|
||||||
|
elog "The meshname daemon will have to be started before use:"
|
||||||
|
if use systemd ; then
|
||||||
|
elog " # systemctl start meshnamed"
|
||||||
|
else
|
||||||
|
elog " # rc-service meshnamed start"
|
||||||
|
fi
|
||||||
|
}
|
28
contrib/meshnamed.initd
Normal file
28
contrib/meshnamed.initd
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
|
||||||
|
extra_started_commands="reload"
|
||||||
|
command="/usr/bin/meshnamed"
|
||||||
|
description="Distributed naming system for IPv6 mesh networks"
|
||||||
|
pidfile="/run/meshnamed.pid"
|
||||||
|
logfile="/var/run/meshnamed.log"
|
||||||
|
start_stop_daemon_args="--user nobody --group nobody -listenaddr '[::1]:53535'"
|
||||||
|
|
||||||
|
start() {
|
||||||
|
ebegin "Starting Distributed naming system for IPv6 mesh networks"
|
||||||
|
start-stop-daemon --start --exec "${command}" --pidfile "${pidfile}" --background \
|
||||||
|
--stdout "${logfile}" --stderr "${logfile}"
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
ebegin "Distributed naming system for IPv6 mesh networks"
|
||||||
|
start-stop-daemon --stop --exec "${command}" --pidfile "${pidfile}"
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
stop
|
||||||
|
sleep 5
|
||||||
|
start
|
||||||
|
}
|
1895
img/logo-maximum.ai
Normal file
1895
img/logo-maximum.ai
Normal file
File diff suppressed because one or more lines are too long
BIN
img/logo-maximum.png
Normal file
BIN
img/logo-maximum.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
1
img/logo-maximum.svg
Normal file
1
img/logo-maximum.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 878.03 168"><defs><style>.a{fill:#8cc63f;}.b{fill:#f2f2f2;}.c{fill:#006837;}</style></defs><title>logo-ver2</title><rect class="a" x="1" y="29" width="877.03" height="139"/><rect width="877.03" height="13"/><path d="M137.54,469.46V397.84L124.4,384.66H112.52L99.38,397.84v71.62H86.66V392.55l20.78-20.61h22l14.42,14.2,14.42-14.2h22.05l20.77,20.61v76.91H188.42V397.84l-13.14-13.18H163.41l-13.15,13.18v71.62Z" transform="translate(-65 -319)"/><path d="M277.89,469.46h-39L218.1,448.85v-56.3l20.78-20.61h39l20.77,20.56v22.26l-20.77,20.78H235.06V422.82H272.8l13.14-13.36V397.8L272.8,384.66H244l-13.15,13.18v45.72L244,457H272.8l19.5-19.71,8.91,9.11Z" transform="translate(-65 -319)"/><path d="M378,469.46H318.16V457h54.7L386,443.5V427.06H318.16V392.5l20.78-20.56h59.79v12.72H344L330.89,397.8v16.54h67.84v34.48Z" transform="translate(-65 -319)"/><path d="M415.69,469.46V326h12.72v53.78l8-7.84h39l20.78,20.61v76.91H483.53V397.84l-13.15-13.18H441.55l-13.14,13.18v71.62Z" transform="translate(-65 -319)"/><path class="b" d="M581.05,446V391.61l-13.15-10H539.07l-13.14,10V446H513.21V387.59L534,371.94h39l20.78,15.65V446Z" transform="translate(-65 -319)"/><path class="b" d="M670.51,470h-39l-20.77-20.75V426.8l20.77-20.75h42.83v12.79H636.59l-13.14,13.29v11.79l13.14,13.5h28.83L678.57,444V398l-13.15-13.26H627.69V371.94h42.82l20.78,20.72v56.62Z" transform="translate(-65 -319)"/><path class="b" d="M759.13,470V398L746,384.73H734.11L721,398v72H708.25V392.66L729,371.94h22.05l14.42,14.28,14.41-14.28H802l20.78,20.72V470H810V398l-13.14-13.25H785L771.85,398v72Z" transform="translate(-65 -319)"/><path class="b" d="M899.47,470h-39l-20.78-20.72V392.66l20.78-20.72h39l20.78,20.68V415l-20.78,20.89H856.65V423.1h37.74l13.14-13.43V398l-13.14-13.22H865.55L852.41,398v46l13.14,13.47h28.84l19.5-19.82,8.91,9.16Z" transform="translate(-65 -319)"/><path class="c" d="M513,469.15V457h1.67a2.12,2.12,0,0,1,2.39,2.17v7.95c0,1.25-1,2-2.55,2Zm1.08-.92h.43c1,0,1.47-.36,1.47-1.11v-7.95c0-.83-.45-1.25-1.31-1.25h-.59Z" transform="translate(-65 -319)"/><path class="c" d="M519.91,467.43v-8.71a2.06,2.06,0,0,1,4.06,0v8.71a2.06,2.06,0,0,1-4.06,0Zm1.08-8.71v8.71a1,1,0,0,0,1.9,0v-8.71a1,1,0,0,0-1.9,0Z" transform="translate(-65 -319)"/><path class="c" d="M526.42,467.43v-8.71a2.06,2.06,0,0,1,4.06,0v8.71a2.06,2.06,0,0,1-4.06,0Zm1.08-8.71v8.71a1,1,0,0,0,1.9,0v-8.71a1,1,0,0,0-1.9,0Z" transform="translate(-65 -319)"/><path class="c" d="M538.33,469.15h-1.08v-8l-1,3.16h-.9l-1-3.16v8h-1.08V457h1l1.53,5.09,1.53-5.09h1Z" transform="translate(-65 -319)"/><path class="c" d="M541.6,467.43V465.9h1.08v1.53a1,1,0,0,0,1.9,0v-2.17a2.56,2.56,0,0,0-1.33-2.13,3.44,3.44,0,0,1-1.65-2.82v-1.59a2.06,2.06,0,0,1,4.06,0v1.44h-1.08v-1.44a1,1,0,0,0-1.9,0v1.59a2.61,2.61,0,0,0,1.33,2.16,3.39,3.39,0,0,1,1.65,2.79v2.17a2.06,2.06,0,0,1-4.06,0Z" transform="translate(-65 -319)"/><path class="c" d="M548.93,469.15V457h1.67a2.12,2.12,0,0,1,2.39,2.17v7.95c0,1.25-1,2-2.55,2Zm1.08-.92h.43c1,0,1.47-.36,1.47-1.11v-7.95c0-.83-.45-1.25-1.31-1.25H550Z" transform="translate(-65 -319)"/><path class="c" d="M559.64,469.15l-.53-2.78h-2.43l-.55,2.78H555L557.44,457h.92l2.39,12.15Zm-2.77-3.7h2.06l-1-5.22Z" transform="translate(-65 -319)"/><path class="c" d="M566.22,457h1.1l-1.92,7.24v4.91h-1.08v-4.91L562.38,457h1.1l1.37,5.12Z" transform="translate(-65 -319)"/><path class="c" d="M575.28,469.15V457H577a2.12,2.12,0,0,1,2.39,2.17v7.95c0,1.25-1,2-2.55,2Zm1.08-.92h.43c1,0,1.47-.36,1.47-1.11v-7.95c0-.83-.45-1.25-1.31-1.25h-.59Z" transform="translate(-65 -319)"/><path class="c" d="M585.69,469.15l-2-7.55v7.55h-1.08V457h1l2,7.55V457h1.08v12.15Z" transform="translate(-65 -319)"/><path class="c" d="M589.94,467.43V465.9H591v1.53a1,1,0,0,0,1.9,0v-2.17a2.56,2.56,0,0,0-1.33-2.13,3.44,3.44,0,0,1-1.65-2.82v-1.59a2.06,2.06,0,0,1,4.06,0v1.44h-1.08v-1.44a1,1,0,0,0-1.9,0v1.59a2.61,2.61,0,0,0,1.33,2.16,3.39,3.39,0,0,1,1.65,2.79v2.17a2.06,2.06,0,0,1-4.06,0Z" transform="translate(-65 -319)"/></svg>
|
After Width: | Height: | Size: 3.9 KiB |
1935
img/logo-medium.ai
Normal file
1935
img/logo-medium.ai
Normal file
File diff suppressed because one or more lines are too long
BIN
img/logo-medium.png
Normal file
BIN
img/logo-medium.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
1
img/logo-medium.svg
Normal file
1
img/logo-medium.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 878.03 168"><defs><style>.a{fill:#8cc63f;}.b{fill:#f2f2f2;}.c{fill:#006837;}</style></defs><title>logo-ver1</title><rect class="a" x="1" y="29" width="877.03" height="139"/><rect width="877.03" height="13"/><path d="M137.54,469.46V397.84L124.4,384.66H112.52L99.38,397.84v71.62H86.66V392.55l20.78-20.61h22l14.42,14.2,14.42-14.2h22.05l20.77,20.61v76.91H188.42V397.84l-13.14-13.18H163.41l-13.15,13.18v71.62Z" transform="translate(-65 -319)"/><path d="M277.89,469.46h-39L218.1,448.85v-56.3l20.78-20.61h39l20.77,20.56v22.26l-20.77,20.78H235.06V422.82H272.8l13.14-13.36V397.8L272.8,384.66H244l-13.15,13.18v45.72L244,457H272.8l19.5-19.71,8.91,9.11Z" transform="translate(-65 -319)"/><path d="M378,469.46H318.16V457h54.7L386,443.5V427.06H318.16V392.5l20.78-20.56h59.79v12.72H344L330.89,397.8v16.54h67.84v34.48Z" transform="translate(-65 -319)"/><path d="M415.69,469.46V326h12.72v53.78l8-7.84h39l20.78,20.61v76.91H483.53V397.84l-13.15-13.18H441.55l-13.14,13.18v71.62Z" transform="translate(-65 -319)"/><path class="b" d="M581.05,446V391.61l-13.15-10H539.07l-13.14,10V446H513.21V387.59L534,371.94h39l20.78,15.65V446Z" transform="translate(-65 -319)"/><path class="b" d="M670.51,446h-39l-20.77-15.67v-17L631.5,397.7h42.83v9.66H636.59l-13.14,10v8.9l13.14,10.2h28.83l13.15-10.17V391.61l-13.15-10H627.69v-9.66h42.82l20.78,15.65v42.76Z" transform="translate(-65 -319)"/><path class="b" d="M759.13,446V391.61L746,381.6H734.11l-13.14,10V446H708.25V387.59L729,371.94h22.05l14.42,10.79,14.41-10.79H802l20.78,15.65V446H810V391.61l-13.14-10H785l-13.14,10V446Z" transform="translate(-65 -319)"/><path class="b" d="M899.47,446h-39l-20.78-15.65V387.59l20.78-15.65h39l20.78,15.62v16.9l-20.78,15.78H856.65v-9.66h37.74l13.14-10.14v-8.86l-13.14-10H865.55l-13.14,10v34.72l13.14,10.17h28.84l19.5-15,8.91,6.92Z" transform="translate(-65 -319)"/><path class="c" d="M513,469.15V457h8.41c7.39,0,12,.83,12,2.17v7.95c0,1.25-4.92,2-12.82,2Zm5.44-.92h2.15c4.92,0,7.39-.36,7.39-1.11v-7.95c0-.83-2.26-1.25-6.57-1.25h-3Z" transform="translate(-65 -319)"/><path class="c" d="M547.72,467.43v-8.71c0-.94,4.62-1.72,10.16-1.72s10.25.78,10.25,1.72v8.71c0,.94-4.61,1.72-10.25,1.72S547.72,468.37,547.72,467.43Zm5.44-8.71v8.71c0,.44,2.15.8,4.72.8s4.82-.36,4.82-.8v-8.71c0-.44-2.16-.8-4.82-.8S553.16,458.28,553.16,458.72Z" transform="translate(-65 -319)"/><path class="c" d="M580.44,467.43v-8.71c0-.94,4.62-1.72,10.15-1.72s10.26.78,10.26,1.72v8.71c0,.94-4.61,1.72-10.26,1.72S580.44,468.37,580.44,467.43Zm5.44-8.71v8.71c0,.44,2.15.8,4.71.8s4.83-.36,4.83-.8v-8.71c0-.44-2.16-.8-4.83-.8S585.88,458.28,585.88,458.72Z" transform="translate(-65 -319)"/><path class="c" d="M640.29,469.15h-5.43v-8L630,464.27h-4.51l-4.82-3.16v8h-5.44V457h4.82l7.7,5.09,7.69-5.09h4.82Z" transform="translate(-65 -319)"/><path class="c" d="M656.7,467.43V465.9h5.44v1.53c0,.44,2.15.8,4.72.8s4.82-.36,4.82-.8v-2.17c0-1.07-3.08-1.56-6.67-2.13-3.9-.63-8.31-1.34-8.31-2.81v-1.6c0-.94,4.62-1.72,10.16-1.72s10.25.78,10.25,1.72v1.44h-5.43v-1.44c0-.44-2.16-.8-4.82-.8s-4.72.36-4.72.8v1.6c0,1.07,3.08,1.57,6.66,2.15,3.9.62,8.31,1.32,8.31,2.79v2.17c0,.94-4.61,1.72-10.25,1.72S656.7,468.37,656.7,467.43Z" transform="translate(-65 -319)"/><path class="c" d="M693.52,469.15V457h8.41c7.39,0,12,.83,12,2.17v7.95c0,1.25-4.93,2-12.83,2Zm5.44-.92h2.15c4.93,0,7.39-.36,7.39-1.11v-7.95c0-.83-2.26-1.25-6.57-1.25h-3Z" transform="translate(-65 -319)"/><path class="c" d="M747.37,469.15l-2.66-2.78H732.5l-2.77,2.78h-5.54L736.29,457h4.62l12,12.15Zm-14-3.7h10.36l-5.23-5.22Z" transform="translate(-65 -319)"/><path class="c" d="M780.4,457h5.54l-9.64,7.24v4.91h-5.44v-4.91L761.12,457h5.53l6.88,5.12Z" transform="translate(-65 -319)"/><path class="c" d="M825.94,469.15V457h8.41c7.39,0,12,.83,12,2.17v7.95c0,1.25-4.92,2-12.82,2Zm5.44-.92h2.15c4.93,0,7.39-.36,7.39-1.11v-7.95c0-.83-2.26-1.25-6.57-1.25h-3Z" transform="translate(-65 -319)"/><path class="c" d="M878.25,469.15l-10-7.55v7.55h-5.44V457h4.93l10,7.55V457h5.44v12.15Z" transform="translate(-65 -319)"/><path class="c" d="M899.59,467.43V465.9H905v1.53c0,.44,2.16.8,4.72.8s4.82-.36,4.82-.8v-2.17c0-1.07-3.08-1.56-6.66-2.13-3.9-.63-8.31-1.34-8.31-2.81v-1.6c0-.94,4.61-1.72,10.15-1.72s10.26.78,10.26,1.72v1.44h-5.44v-1.44c0-.44-2.15-.8-4.82-.8s-4.72.36-4.72.8v1.6c0,1.07,3.08,1.57,6.67,2.15,3.9.62,8.31,1.32,8.31,2.79v2.17c0,.94-4.62,1.72-10.26,1.72S899.59,468.37,899.59,467.43Z" transform="translate(-65 -319)"/></svg>
|
After Width: | Height: | Size: 4.3 KiB |
1946
img/logo-minimum.ai
Normal file
1946
img/logo-minimum.ai
Normal file
File diff suppressed because one or more lines are too long
BIN
img/logo-minimum.png
Normal file
BIN
img/logo-minimum.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
1
img/logo-minimum.svg
Normal file
1
img/logo-minimum.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 877.06 166"><defs><style>.a{fill:#8cc63f;}.b{fill:#f2f2f2;}</style></defs><title>logo</title><rect class="a" x="0.03" y="27" width="877.03" height="139"/><rect width="877.03" height="13"/><path d="M137.54,469.46V397.84L124.4,384.66H112.52L99.38,397.84v71.62H86.66V392.55l20.78-20.61h22l14.42,14.2,14.42-14.2h22.05l20.77,20.61v76.91H188.42V397.84l-13.14-13.18H163.41l-13.15,13.18v71.62Z" transform="translate(-65.97 -321)"/><path d="M277.89,469.46h-39L218.1,448.85v-56.3l20.78-20.61h39l20.77,20.56v22.26l-20.77,20.78H235.06V422.82H272.8l13.14-13.36V397.8L272.8,384.66H244l-13.15,13.18v45.72L244,457H272.8l19.5-19.71,8.91,9.11Z" transform="translate(-65.97 -321)"/><path d="M378,469.46H318.16V457h54.7L386,443.5V427.06H318.16V392.5l20.78-20.56h59.79v12.72H344L330.89,397.8v16.54h67.84v34.48Z" transform="translate(-65.97 -321)"/><path d="M415.69,469.46V326h12.72v53.78l8-7.84h39l20.78,20.61v76.91H483.53V397.84l-13.15-13.18H441.55l-13.14,13.18v71.62Z" transform="translate(-65.97 -321)"/><path class="b" d="M581.05,469.46V397.84L567.9,384.66H539.07l-13.14,13.18v71.62H513.21V392.55L534,371.94h39l20.78,20.61v76.91Z" transform="translate(-65.97 -321)"/><path class="b" d="M670.51,469.46h-39l-20.77-20.63V426.49l20.77-20.63h42.83v12.72H636.59L623.45,431.8v11.72L636.59,457h28.83l13.15-13.39V397.84l-13.15-13.18H627.69V371.94h42.82l20.78,20.61v56.3Z" transform="translate(-65.97 -321)"/><path class="b" d="M759.13,469.46V397.84L746,384.66H734.11L721,397.84v71.62H708.25V392.55L729,371.94h22.05l14.42,14.2,14.41-14.2H802l20.78,20.61v76.91H810V397.84l-13.14-13.18H785l-13.14,13.18v71.62Z" transform="translate(-65.97 -321)"/><path class="b" d="M899.47,469.46h-39l-20.78-20.61v-56.3l20.78-20.61h39l20.78,20.56v22.26l-20.78,20.78H856.65V422.82h37.74l13.14-13.36V397.8l-13.14-13.14H865.55l-13.14,13.18v45.72L865.55,457h28.84l19.5-19.71,8.91,9.11Z" transform="translate(-65.97 -321)"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |
1
img/readme.md
Normal file
1
img/readme.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Логотип проекта, не облагаемый какими-либо лицензионными обязательствами.
|
@ -9,7 +9,7 @@ Group=nogroup
|
|||||||
ProtectHome=true
|
ProtectHome=true
|
||||||
ProtectSystem=true
|
ProtectSystem=true
|
||||||
SyslogIdentifier=meshnamed
|
SyslogIdentifier=meshnamed
|
||||||
ExecStart=/usr/local/bin/meshnamed -listenaddr [::1]:53535 -useconffile /etc/meshnamed.conf
|
ExecStart=/usr/local/bin/meshnamed -listenaddr [::1]:53535
|
||||||
Restart=always
|
Restart=always
|
||||||
TimeoutStopSec=5
|
TimeoutStopSec=5
|
||||||
|
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
package meshname
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GenConf(target, zone string) (string, error) {
|
|
||||||
ip := net.ParseIP(target)
|
|
||||||
if ip == nil {
|
|
||||||
return "", errors.New("Invalid IP address")
|
|
||||||
}
|
|
||||||
subDomain := DomainFromIP(&ip)
|
|
||||||
selfRecord := fmt.Sprintf("\t\t\"%s.%s AAAA %s\"\n", subDomain, zone, target)
|
|
||||||
confString := fmt.Sprintf("{\n\t\"%s\":[\n%s\t]\n}", subDomain, selfRecord)
|
|
||||||
|
|
||||||
return confString, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load dnsRecords from a JSON file
|
|
||||||
func ParseConfigFile(configPath string) (map[string][]dns.RR, error) {
|
|
||||||
conf, err := ioutil.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var dat map[string][]string
|
|
||||||
if err := json.Unmarshal(conf, &dat); err == nil {
|
|
||||||
return ParseDNSRecordsMap(dat)
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDNSRecordsMap takes a string map and returns a resource record map
|
|
||||||
func ParseDNSRecordsMap(dnsRecordsMap map[string][]string) (map[string][]dns.RR, error) {
|
|
||||||
var dnsRecords = make(map[string][]dns.RR)
|
|
||||||
for subDomain, records := range dnsRecordsMap {
|
|
||||||
for _, r := range records {
|
|
||||||
if rr, err := dns.NewRR(r); err == nil {
|
|
||||||
dnsRecords[subDomain] = append(dnsRecords[subDomain], rr)
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dnsRecords, nil
|
|
||||||
}
|
|
@ -3,8 +3,8 @@ package meshname
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
@ -16,27 +16,27 @@ type MeshnameServer struct {
|
|||||||
dnsClient *dns.Client
|
dnsClient *dns.Client
|
||||||
dnsServer *dns.Server
|
dnsServer *dns.Server
|
||||||
networks map[string]*net.IPNet
|
networks map[string]*net.IPNet
|
||||||
allowRemote bool
|
meshipNetworks map[string]*net.IPNet
|
||||||
|
enableMeshIP bool
|
||||||
dnsRecordsLock sync.RWMutex
|
acmePort string
|
||||||
dnsRecords map[string][]dns.RR
|
|
||||||
|
|
||||||
startedLock sync.RWMutex
|
startedLock sync.RWMutex
|
||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New is a constructor for MeshnameServer
|
// New is a constructor for MeshnameServer
|
||||||
func New(log *log.Logger, listenAddr string, networks map[string]*net.IPNet, allowRemote bool) *MeshnameServer {
|
func New(log *log.Logger, listenAddr string, networks map[string]*net.IPNet, meshipNetworks map[string]*net.IPNet, enableMeshIP bool, acmePort string) *MeshnameServer {
|
||||||
dnsClient := new(dns.Client)
|
dnsClient := new(dns.Client)
|
||||||
dnsClient.Timeout = 5000000000 // increased 5 seconds timeout
|
dnsClient.Timeout = 5000000000 // increased 5 seconds timeout
|
||||||
|
|
||||||
return &MeshnameServer{
|
return &MeshnameServer{
|
||||||
log: log,
|
log: log,
|
||||||
listenAddr: listenAddr,
|
listenAddr: listenAddr,
|
||||||
dnsRecords: make(map[string][]dns.RR),
|
|
||||||
networks: networks,
|
networks: networks,
|
||||||
|
meshipNetworks: meshipNetworks,
|
||||||
dnsClient: dnsClient,
|
dnsClient: dnsClient,
|
||||||
allowRemote: allowRemote,
|
enableMeshIP: enableMeshIP,
|
||||||
|
acmePort: acmePort,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,13 +61,20 @@ func (s *MeshnameServer) Start() error {
|
|||||||
s.dnsServer = &dns.Server{
|
s.dnsServer = &dns.Server{
|
||||||
Addr: s.listenAddr,
|
Addr: s.listenAddr,
|
||||||
Net: "udp",
|
Net: "udp",
|
||||||
NotifyStartedFunc: func(){ close(waitStarted) },
|
NotifyStartedFunc: func() { close(waitStarted) },
|
||||||
|
}
|
||||||
|
if s.enableMeshIP {
|
||||||
|
for mtld, subnet := range s.meshipNetworks {
|
||||||
|
dns.HandleFunc(mtld, s.handleMeshIPRequest)
|
||||||
|
s.log.Debugln("Handling as meship:", mtld, subnet)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for tld, subnet := range s.networks {
|
for tld, subnet := range s.networks {
|
||||||
dns.HandleFunc(tld, s.handleRequest)
|
dns.HandleFunc(tld, s.handleMeshnameRequest)
|
||||||
s.log.Debugln("Handling:", tld, subnet)
|
s.log.Debugln("Handling:", tld, subnet)
|
||||||
}
|
}
|
||||||
go func(){
|
|
||||||
|
go func() {
|
||||||
if err := s.dnsServer.ListenAndServe(); err != nil {
|
if err := s.dnsServer.ListenAndServe(); err != nil {
|
||||||
s.log.Fatalln("MeshnameServer failed to start:", err)
|
s.log.Fatalln("MeshnameServer failed to start:", err)
|
||||||
}
|
}
|
||||||
@ -82,63 +89,91 @@ func (s *MeshnameServer) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshnameServer) ConfigureDNSRecords(dnsRecords map[string][]dns.RR) {
|
func (s *MeshnameServer) handleMeshnameRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
s.dnsRecordsLock.Lock()
|
|
||||||
s.dnsRecords = dnsRecords
|
|
||||||
s.dnsRecordsLock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MeshnameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
var remoteLookups = make(map[string][]dns.Question)
|
var remoteLookups = make(map[string][]dns.Question)
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetReply(r)
|
m.SetReply(r)
|
||||||
s.log.Debugln(r.String())
|
|
||||||
|
|
||||||
s.dnsRecordsLock.RLock()
|
var tldList []string
|
||||||
|
for tld := range s.networks {
|
||||||
|
tldList = append(tldList, tld)
|
||||||
|
}
|
||||||
|
|
||||||
for _, q := range r.Question {
|
for _, q := range r.Question {
|
||||||
labels := dns.SplitDomainName(q.Name)
|
labels := dns.SplitDomainName(q.Name)
|
||||||
if len(labels) < 2 {
|
if len(labels) < 2 {
|
||||||
s.log.Debugln("Error: invalid domain requested")
|
s.log.Debugln("Error: invalid domain requested")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
subDomain := labels[len(labels)-2]
|
|
||||||
|
|
||||||
if records, ok := s.dnsRecords[subDomain]; ok {
|
// process domain
|
||||||
for _, rec := range records {
|
input := strings.ToLower(strings.TrimSuffix(q.Name, "."))
|
||||||
if h := rec.Header(); h.Name == q.Name && h.Rrtype == q.Qtype && h.Class == q.Qclass {
|
subDomain := ""
|
||||||
m.Answer = append(m.Answer, rec)
|
tld := ""
|
||||||
|
for i := range tldList {
|
||||||
|
t := strings.ToLower(tldList[i])
|
||||||
|
if strings.HasSuffix(input, "."+t) {
|
||||||
|
// define tld
|
||||||
|
tld = t
|
||||||
|
domainParts := strings.SplitN(input, "."+t, 2)
|
||||||
|
firstPart := domainParts[0]
|
||||||
|
firstPartLabels := dns.SplitDomainName(firstPart)
|
||||||
|
// define hostname ("subDomain")
|
||||||
|
subDomain = firstPartLabels[len(firstPartLabels)-1]
|
||||||
|
if len(firstPartLabels) == 1 && q.Qtype == dns.TypeAAAA {
|
||||||
|
s.handleMeshIPRequest(w, r)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if s.isRemoteLookupAllowed(w.RemoteAddr()) {
|
}
|
||||||
// do remote lookups only for local clients
|
|
||||||
resolvedAddr, err := IPFromDomain(&subDomain)
|
resolvedAddr, err := IPFromDomain(&subDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Debugln(err)
|
s.log.Debugln(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// check subnet validity
|
|
||||||
tld := labels[len(labels)-1]
|
|
||||||
|
|
||||||
|
// check subnet validity
|
||||||
if subnet, ok := s.networks[tld]; ok && subnet.Contains(resolvedAddr) {
|
if subnet, ok := s.networks[tld]; ok && subnet.Contains(resolvedAddr) {
|
||||||
remoteLookups[resolvedAddr.String()] = append(remoteLookups[resolvedAddr.String()], q)
|
remoteLookups[resolvedAddr.String()] = append(remoteLookups[resolvedAddr.String()], q)
|
||||||
} else {
|
} else {
|
||||||
s.log.Debugln("Error: subnet doesn't match")
|
s.log.Debugln("Error: subnet doesn't match")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
s.dnsRecordsLock.RUnlock()
|
|
||||||
|
|
||||||
for remoteServer, questions := range remoteLookups {
|
for remoteServer, questions := range remoteLookups {
|
||||||
rm := new(dns.Msg)
|
rm := new(dns.Msg)
|
||||||
rm.RecursionDesired = true
|
rm.RecursionDesired = true
|
||||||
rm.Question = questions
|
rm.Question = questions
|
||||||
resp, _, err := s.dnsClient.Exchange(rm, "["+remoteServer+"]:53") // no retries
|
// always use lowercase internally among meshname instances
|
||||||
if err != nil {
|
originalQuestionName := rm.Question[0].Name
|
||||||
s.log.Debugln(err)
|
// mocking spongebob dns encoding support
|
||||||
continue
|
rm.Question[0].Name = strings.ToLower(originalQuestionName)
|
||||||
|
// add alternative port number
|
||||||
|
portNumbers := []string{"53"}
|
||||||
|
portNumbers = append([]string{s.acmePort}, portNumbers...) // TODO: rename acmePort to alternativePort
|
||||||
|
// make request
|
||||||
|
err := error(nil)
|
||||||
|
for _, port := range portNumbers {
|
||||||
|
s.log.Debugln("trying port:"+port)
|
||||||
|
resp, _, err := s.dnsClient.Exchange(rm, "["+remoteServer+"]:"+port)
|
||||||
|
// if we had success we don't keep trying other ports
|
||||||
|
if err == nil {
|
||||||
|
if len(resp.Answer) > 0 {
|
||||||
|
// mocking spongebob dns encoding support
|
||||||
|
resp.Question[0].Name = originalQuestionName
|
||||||
|
resp.Answer[0].Header().Name = originalQuestionName
|
||||||
}
|
}
|
||||||
s.log.Debugln(resp.String())
|
s.log.Debugln(resp.String())
|
||||||
m.Answer = append(m.Answer, resp.Answer...)
|
m.Answer = append(m.Answer, resp.Answer...)
|
||||||
|
m.Ns = append(m.Ns, resp.Ns...)
|
||||||
|
m.Extra = append(m.Extra, resp.Extra...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
s.log.Debugln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := w.WriteMsg(m); err != nil {
|
if err := w.WriteMsg(m); err != nil {
|
||||||
@ -146,13 +181,27 @@ func (s *MeshnameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshnameServer) isRemoteLookupAllowed(addr net.Addr) bool {
|
func (s *MeshnameServer) handleMeshIPRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
// TODO prefix whitelists ?
|
m := new(dns.Msg)
|
||||||
if s.allowRemote {
|
m.SetReply(r)
|
||||||
return true
|
m.Authoritative = true
|
||||||
|
|
||||||
|
for _, q := range r.Question {
|
||||||
|
labels := dns.SplitDomainName(q.Name)
|
||||||
|
if resolvedAddr, err := IPFromDomain(&labels[0]); err == nil {
|
||||||
|
answer := new(dns.AAAA)
|
||||||
|
answer.Hdr = dns.RR_Header{Name: q.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 3600}
|
||||||
|
answer.AAAA = resolvedAddr
|
||||||
|
m.Answer = append(m.Answer, answer)
|
||||||
|
s.log.Debugln(m)
|
||||||
|
} else {
|
||||||
|
s.log.Debugln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.WriteMsg(m); err != nil {
|
||||||
|
s.log.Debugln("Error writing response:", err)
|
||||||
}
|
}
|
||||||
ra := addr.String()
|
|
||||||
return strings.HasPrefix(ra, "[::1]:") || strings.HasPrefix(ra, "127.0.0.1:")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MeshnameServer) IsStarted() bool {
|
func (s *MeshnameServer) IsStarted() bool {
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
package meshname
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gologme/log"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
|
|
||||||
"github.com/zhoreeq/meshname/pkg/meshname"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServerLocalDomain(t *testing.T) {
|
|
||||||
bindAddr := "[::1]:54545"
|
|
||||||
log := log.New(os.Stdout, "", log.Flags())
|
|
||||||
yggIPNet := &net.IPNet{IP: net.ParseIP("200::"), Mask: net.CIDRMask(7, 128)}
|
|
||||||
networks := map[string]*net.IPNet{"meshname": yggIPNet}
|
|
||||||
allowRemote := false
|
|
||||||
|
|
||||||
ts := meshname.New(log, bindAddr, networks, allowRemote)
|
|
||||||
|
|
||||||
exampleConfig := make(map[string][]string)
|
|
||||||
exampleConfig["aiarnf2wpqjxkp6rhivuxbondy"] = append(exampleConfig["aiarnf2wpqjxkp6rhivuxbondy"],
|
|
||||||
"test.aiarnf2wpqjxkp6rhivuxbondy.meshname. AAAA 201:1697:567c:1375:3fd1:3a2b:4b85:cd1e")
|
|
||||||
|
|
||||||
if dnsRecords, err := meshname.ParseDNSRecordsMap(exampleConfig); err == nil {
|
|
||||||
ts.ConfigureDNSRecords(dnsRecords)
|
|
||||||
} else {
|
|
||||||
t.Fatalf("meshname: Failed to parse Meshname config: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ts.Start()
|
|
||||||
|
|
||||||
tc := new(dns.Client)
|
|
||||||
m := new(dns.Msg)
|
|
||||||
m.SetQuestion("test.aiarnf2wpqjxkp6rhivuxbondy.meshname.", dns.TypeAAAA)
|
|
||||||
resp, _, err := tc.Exchange(m, bindAddr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(resp.Answer) != 1 {
|
|
||||||
t.Fatalf("Invalid response: %s", resp.String())
|
|
||||||
}
|
|
||||||
if !strings.Contains(resp.Answer[0].String(), "201:1697:567c:1375:3fd1:3a2b:4b85:cd1e") {
|
|
||||||
t.Fatalf("Invalid IP in response: %s", resp.Answer[0].String())
|
|
||||||
}
|
|
||||||
|
|
||||||
ts.Stop()
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user