feat(lns): parse dns= records from alias comments as fallback
- When HSD sidechain returns null for a name, fall back to parsing dns= field from the main chain alias comment - Format: dns=A:@:1.2.3.4,CNAME:www:lthn.io,TXT:@:value - ParseDNSFromComment extracts records and adds to cache - Names registered via Blesta now resolve through LNS - Always sync (removed tree root skip) to catch new alias comments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f917d3e994
commit
5b4d199442
3 changed files with 117 additions and 5 deletions
|
|
@ -98,6 +98,79 @@ func getChainAliases() []ChainAlias {
|
|||
return aliases
|
||||
}
|
||||
|
||||
// ParseDNSFromComment extracts DNS records from an alias comment's dns= field.
|
||||
// Format: dns=A:@:1.2.3.4,AAAA:@:2001:db8::1,CNAME:www:lthn.io
|
||||
//
|
||||
// records := ParseDNSFromComment("v=lthn1;type=user;dns=A:@:10.69.69.165,TXT:@:hello")
|
||||
func ParseDNSFromComment(comment string) *NameRecord {
|
||||
parsed := parseAliasComment(comment)
|
||||
dnsField, hasDNS := parsed["dns"]
|
||||
if !hasDNS || dnsField == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
record := &NameRecord{}
|
||||
entries := splitComma(dnsField)
|
||||
for _, entry := range entries {
|
||||
parts := splitColon(entry, 3)
|
||||
if len(parts) < 3 {
|
||||
continue
|
||||
}
|
||||
recordType := parts[0]
|
||||
value := parts[2]
|
||||
switch recordType {
|
||||
case "A":
|
||||
record.A = append(record.A, value)
|
||||
case "AAAA":
|
||||
record.AAAA = append(record.AAAA, value)
|
||||
case "CNAME":
|
||||
record.A = append(record.A, value) // CNAME stored as A for resolution
|
||||
case "TXT":
|
||||
record.TXT = append(record.TXT, value)
|
||||
case "NS":
|
||||
record.NS = append(record.NS, value)
|
||||
}
|
||||
}
|
||||
if len(record.A) == 0 && len(record.AAAA) == 0 && len(record.TXT) == 0 && len(record.NS) == 0 {
|
||||
return nil
|
||||
}
|
||||
return record
|
||||
}
|
||||
|
||||
func splitComma(input string) []string {
|
||||
parts := make([]string, 0)
|
||||
current := ""
|
||||
for _, character := range input {
|
||||
if character == ',' {
|
||||
if current != "" {
|
||||
parts = append(parts, current)
|
||||
}
|
||||
current = ""
|
||||
} else {
|
||||
current += string(character)
|
||||
}
|
||||
}
|
||||
if current != "" {
|
||||
parts = append(parts, current)
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
func splitColon(input string, maxParts int) []string {
|
||||
parts := make([]string, 0, maxParts)
|
||||
current := ""
|
||||
for _, character := range input {
|
||||
if character == ':' && len(parts) < maxParts-1 {
|
||||
parts = append(parts, current)
|
||||
current = ""
|
||||
} else {
|
||||
current += string(character)
|
||||
}
|
||||
}
|
||||
parts = append(parts, current)
|
||||
return parts
|
||||
}
|
||||
|
||||
// parseAliasComment extracts key=value pairs from a v=lthn1 alias comment.
|
||||
//
|
||||
// parseAliasComment("v=lthn1;type=gateway;cap=vpn,dns")
|
||||
|
|
|
|||
|
|
@ -121,18 +121,57 @@ var knownNames = []string{
|
|||
|
||||
func syncCache() {
|
||||
root := getTreeRoot()
|
||||
if root == lastRoot && root != "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Discover names from the main chain, fall back to hardcoded list.
|
||||
names := discoverNames()
|
||||
aliases := getChainAliases()
|
||||
names := make([]string, 0)
|
||||
aliasMap := make(map[string]ChainAlias)
|
||||
|
||||
core.Println(core.Sprintf("[%s] Tree root changed — syncing %d names", time.Now().Format("15:04:05"), len(names)))
|
||||
if len(aliases) > 0 {
|
||||
seen := make(map[string]bool)
|
||||
for _, alias := range aliases {
|
||||
hnsName := alias.Name
|
||||
comment := parseAliasComment(alias.Comment)
|
||||
if hns, ok := comment["hns"]; ok && hns != "" {
|
||||
stripped := core.TrimSuffix(hns, ".lthn")
|
||||
if stripped != "" {
|
||||
hnsName = stripped
|
||||
}
|
||||
}
|
||||
if !seen[hnsName] {
|
||||
seen[hnsName] = true
|
||||
names = append(names, hnsName)
|
||||
aliasMap[hnsName] = alias
|
||||
}
|
||||
}
|
||||
} else {
|
||||
names = knownNames
|
||||
}
|
||||
|
||||
dnsCount := 0
|
||||
for _, a := range aliases { if core.Contains(a.Comment, "dns=") { dnsCount++ } }
|
||||
core.Println(core.Sprintf("[%s] Syncing %d names (%d with dns=, %d in aliasMap)", time.Now().Format("15:04:05"), len(names), dnsCount, len(aliasMap)))
|
||||
for _, name := range names {
|
||||
// Try HSD sidechain first
|
||||
record := getNameRecords(name)
|
||||
if record != nil {
|
||||
cache[name] = record
|
||||
continue
|
||||
}
|
||||
|
||||
// Fall back to dns= entries in alias comment
|
||||
if alias, exists := aliasMap[name]; exists && core.Contains(alias.Comment, "dns=") {
|
||||
record = ParseDNSFromComment(alias.Comment)
|
||||
core.Println(core.Sprintf("[dns=] %s comment=%s record=%v", name, alias.Comment, record != nil))
|
||||
if record != nil {
|
||||
record.Name = name
|
||||
// Add the TXT metadata from the comment itself
|
||||
comment := alias.Comment
|
||||
if comment != "" && len(record.TXT) == 0 {
|
||||
record.TXT = append(record.TXT, comment)
|
||||
}
|
||||
cache[name] = record
|
||||
}
|
||||
}
|
||||
}
|
||||
lastRoot = root
|
||||
|
|
|
|||
BIN
lns
BIN
lns
Binary file not shown.
Loading…
Add table
Reference in a new issue