{"record":{"id":"8f02574fdcbec208","repo":"txthinking/brook","slug":"block-addr","errorCode":null,"errorMessage":"block ${addr}","messagePattern":"block \\$\\{addr\\}","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugins/block/block.go","lineNumber":160,"sourceCode":"\t\tvar c6 []*net.IPNet\n\t\tif bk.Lock != nil {\n\t\t\tbk.Lock.RLock()\n\t\t}\n\t\tds = bk.Domain\n\t\tc4 = bk.CIDR4\n\t\tc6 = bk.CIDR6\n\t\tif bk.Lock != nil {\n\t\t\tbk.Lock.RUnlock()\n\t\t}\n\t\th, _, err := net.SplitHostPort(addr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvar a net.Addr\n\t\tip := net.ParseIP(h)\n\t\tif ip == nil {\n\t\t\tif brook.ListHasDomain(ds, strings.ToLower(h), bk.Cache) {\n\t\t\t\treturn nil, errors.New(\"block \" + addr)\n\t\t\t}\n\t\t\ta, err = f(network, addr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tv, ok := a.(*net.TCPAddr)\n\t\t\tif ok {\n\t\t\t\tip = v.IP\n\t\t\t}\n\t\t\tif !ok {\n\t\t\t\tip = a.(*net.UDPAddr).IP\n\t\t\t}\n\t\t}\n\t\tif brook.ListHasIP(c4, c6, ip, bk.Cache, bk.GeoIP) {\n\t\t\treturn nil, errors.New(\"block \" + addr)\n\t\t}\n\t\tif a != nil {\n\t\t\treturn a, nil","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/plugins/block/block.go#L142-L178","documentation":"The block plugin rejects a connection because the target hostname was found in the configured domain blocklist. brook.ListHasDomain checks the domain (lowercased, via the cache) against the user-supplied domain list, and when it matches, the dial is aborted with \"block <addr>\" instead of connecting.","triggerScenarios":"A client requests a connection whose hostname is present in the domain blocklist file (or matches a list entry) while the brook server runs with the --blockDomainList option.","commonSituations":"Corporate/parental filtering setups where a legitimately requested domain happens to be on the blocklist; overly broad list entries (e.g., a parent domain) blocking subdomains; stale list entries after policy changes.","solutions":["Remove the target domain from the block domain list file (or its parent entry causing the match).","Check the lowercased host \"h\" in the error message against list entries; broaden/narrow list patterns as intended.","Restart brook after editing the list so the cache refreshes.","If the domain should resolve but be IP-filtered instead, move it from the domain list to the IP list configuration."],"exampleFix":"// before (list file)\nads.example.com\ntracker.example.com\n// after: remove the entry that matches your needed domain\n# ads.example.com removed","handlingStrategy":"fallback","validationCode":"// check membership before dialing\nif brook.ListHasDomain(ds, strings.ToLower(host), cache) {\n    log.Printf(\"skipping blocked domain %s\", host)\n}","typeGuard":null,"tryCatchPattern":"if strings.HasPrefix(err.Error(), \"block \") {\n    log.Printf(\"domain blocked by policy: %v\", err)\n    // route via alternate proxy or surface a policy-denied result to the user\n}","preventionTips":["Keep blocklists curated; review entries that are parent domains of needed hosts.","Test new blocklist entries against the set of domains your apps use.","Lowercase hostnames exactly as the plugin does when pre-checking.","Document list file locations and restart procedures for operators."],"tags":["filtering","blocklist","domain","config"],"backgroundTag":"permission-denied","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}