weppos/publicsuffix-go
GitHub: weppos/publicsuffix-go
基于 Public Suffix List 的 Go 域名解析库,提供比标准库更灵活的公共后缀识别和域名结构解析能力。
Stars: 222 | Forks: 36
# Go 的 PublicSuffix
`publicsuffix` 包提供了一个基于 [Public Suffix List](https://publicsuffix.org/) 的 Go 域名解析器。
[](https://github.com/weppos/publicsuffix-go/actions?query=workflow%3ATests)
[](https://pkg.go.dev/github.com/weppos/publicsuffix-go/publicsuffix)
## 要求
`publicsuffix-go` 要求 **Go >= 1.21**。我们尽量不破坏旧版本的 Go,但由于工具链的限制,我们不总是测试旧版本。
## 快速开始
将代码库[克隆到你的工作空间](https://golang.org/doc/code.html#Organization)并进入该目录:
```
mkdir -p $GOPATH/src/github.com/weppos && cd $_
git clone git@github.com:weppos/publicsuffix-go.git
cd publicsuffix-go
```
获取依赖:
```
go get ./...
```
运行测试套件。
```
go test ./...
```
## 安装
```
go get github.com/weppos/publicsuffix-go
```
## 测试
以下命令运行整个测试套件。
```
go test ./...
```
该库内置了 3 个不同的测试套件:
- Acceptance:验收测试套件包含一些高级测试,以确保库按预期运行
- PSL:PSL 测试套件使用[官方 Public Suffix 测试用例](https://github.com/publicsuffix/list/blob/master/tests/tests.txt)对库进行测试
- Unit:单元测试套件对该包的各个单一组件进行压力测试
## 用法
这是一个简单的示例,演示了如何使用默认选项和随库附带的默认 Public Suffix 列表。
```
package main
import (
"fmt"
"github.com/weppos/publicsuffix-go/publicsuffix"
)
func main() {
// Extract the domain from a string
// using the default list
fmt.Println(publicsuffix.Domain("example.com")) // example.com
fmt.Println(publicsuffix.Domain("www.example.com")) // example.com
fmt.Println(publicsuffix.Domain("example.co.uk")) // example.co.uk
fmt.Println(publicsuffix.Domain("www.example.co.uk")) // example.co.uk
// Parse the domain from a string
// using the default list
fmt.Println(publicsuffix.Parse("example.com")) // &DomainName{"com", "example", ""}
fmt.Println(publicsuffix.Parse("www.example.com")) // &DomainName{"com", "example", "www"}
fmt.Println(publicsuffix.Parse("example.co.uk")) // &DomainName{"co.uk", "example", ""}
fmt.Println(publicsuffix.Parse("www.example.co.uk")) // &DomainName{"co.uk", "example", "www"}
}
```
### 私有域名
PSL 由两个后缀列表组成:IANA 后缀和私有域名。
私有域名由私人组织提交。默认情况下,私有域名不会被忽略。
有时,你可能想要忽略这些域名,仅针对 IANA 后缀进行查询。你有两个选择:
1. 在运行时忽略这些域名
2. 创建不包含私有域名的自定义列表
在第一种情况下,私有域名会在运行时被忽略:它们仍然会包含在列表中,但在查找到它们时会跳过。
```
publicsuffix.DomainFromListWithOptions(publicsuffix.DefaultList(), "google.blogspot.com", nil)
// google.blogspot.com
publicsuffix.DomainFromListWithOptions(publicsuffix.DefaultList(), "google.blogspot.com", &publicsuffix.FindOptions{IgnorePrivate: true})
// blogspot.com
// Note that the DefaultFindOptions includes the private domains by default
publicsuffix.DomainFromListWithOptions(publicsuffix.DefaultList(), "google.blogspot.com", publicsuffix.DefaultFindOptions)
// google.blogspot.com
```
这个解决方案很简单,但速度较慢。如果你发现在所有情况下(或在大多数情况下)都需要忽略私有域名,你可能需要创建一个不包含私有域名的自定义列表。
```
list := NewListFromFile("path/to/list.txt", &publicsuffix.ParserOption{PrivateDomains: false})
publicsuffix.DomainFromListWithOptions(list, "google.blogspot.com", nil)
// blogspot.com
```
## IDN 域名,A-label 和 U-label
[A-label 和 U-label](https://tools.ietf.org/html/rfc5890#section-2.3.2.1) 是表示 IDN 域名的两种不同方式。这两种编码也被称为 ASCII(A-label)或 Punycode 与 Unicode(U-label)。U-label 和 A-label 之间的转换按照 ["Punycode" 规范](https://tools.ietf.org/html/rfc3492)进行,并根据需要添加或删除 ACE 前缀。
支持 IDNA 的应用程序通常使用 A-label 形式来存储和处理数据,而 U-label 可以出现在表示和用户界面中。
尽管 PSL 列表传统上采用 U-label 编码,但本库遵循行业标准,以 A-label 形式存储规则。因此,除非明确说明,任何方法调用、比较或内部表示都应是 ASCII 兼容编码 (ACE) 的。
将 Unicode 名称传递给本库可能会导致错误或意外行为。
如果你对这一决定的细节感兴趣,可以在[这里](https://github.com/weppos/publicsuffix-go/issues/31)阅读完整的讨论。
## 与 `golang.org/x/net/publicsuffix` 的区别
[`golang.org/x/net/publicsuffix`](https://godoc.org/golang.org/x/net/publicsuffix) 是 Golang `x/net` 包的一部分,提供了一个公共后缀列表实现。
主要区别在于 `x/net` 包针对速度进行了优化,但灵活性较差。该列表被编译并嵌入到包本身中。然而,这也是它的主要缺点。
[该列表更新的频率不高](https://github.com/letsencrypt/boulder/issues/1374#issuecomment-182429297),因此结果可能不准确,特别是如果你严重依赖列表中的私有域名部分。IANA 部分的更改频率较低,而私有域名部分的更改每周都会发生。
本包提供以下额外功能:
- 能够在运行时加载任意列表(例如,你可以提供自己的列表,或创建多个列表)
- 能够创建多个列表
- 能够使用预先定义的列表解析域名
- 能够向现有列表添加自定义规则,或从其他列表合并/加载规则(以文件或字符串形式提供)
- 对列表规则的高级访问
- 能够在运行时或解析列表时忽略私有域名
本包还致力于与 `x/net` 包保持 100% 的兼容性。提供了一个特殊的适配器作为直接替代品。只需将 include 语句从
```
import (
"golang.org/x/net/publicsuffix"
)
```
更改为
```
import (
"github.com/weppos/publicsuffix-go/net/publicsuffix"
)
```
`github.com/weppos/publicsuffix-go/net/publicsuffix` 包定义了与 `golang.org/x/net/publicsuffix` 中相同的方法,但这些方法是使用 `github.com/weppos/publicsuffix-go/publicsuffix` 包实现的。
请注意,该适配器不提供 `github.com/weppos/publicsuffix-go/publicsuffix` 的灵活性,例如使用多个列表或在运行时禁用私有域名的能力。
## 与 `cookiejar.PublicSuffixList` 一起使用
本包实现了 [`cookiejar.PublicSuffixList` 接口](https://godoc.org/net/http/cookiejar#PublicSuffixList)。这意味着在创建 `net/http/cookiejar` 时,它可以被用作 `PublicSuffixList` 选项的值。
```
import (
"net/http/cookiejar"
"github.com/weppos/publicsuffix-go/publicsuffix"
)
deliciousJar := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.CookieJarList})
```
## 什么是公共后缀列表?
[Public Suffix List](https://publicsuffix.org) 是一项跨供应商的倡议,旨在提供准确的域名后缀列表。
Public Suffix List 是 Mozilla 项目的一项倡议,但作为社区资源进行维护。它可用于任何软件,但最初是为了满足浏览器制造商的需求而创建的。
“公共后缀”是指互联网用户可以直接在其下注册名称的后缀。公共后缀的一些示例包括 “.com”、“.co.uk” 和 “pvt.k12.wy.us”。Public Suffix List 是所有已知公共后缀的列表。
## 为什么使用公共后缀列表而不是正则表达式?
以前,浏览器使用的算法基本上只拒绝为没有点的顶级域名(例如 com 或 org)设置范围广泛的 cookie。但是,这不适用于仅允许三级域名注册的顶级域名(例如 co.uk)。在这些情况下,网站可以为 co.uk 设置 cookie,并且该 cookie 将传递给在 co.uk 下注册的每个网站。
显然,这是一个安全风险,因为它允许设置 cookie 的网站以外的其他网站读取它,从而可能提取敏感信息。
由于没有算法方法可以找出特定顶级域名可以注册的最高级别(每个注册局的政策不同),因此唯一的方法是创建一个包含所有顶级域名及其下可以注册域名的级别的列表。这就是有效 TLD 列表的目标。
除了用于防止在不该设置 cookie 的地方设置 cookie 外,该列表还可能用于其他需要了解域名注册局控制部分和私人控制部分的应用程序,例如按顶级域名进行分组时。
来源:https://wiki.mozilla.org/Public_Suffix_List
还不信吗?看看[这个真实案例](https://stackoverflow.com/q/288810/123527)。
## PublicSuffix 会发起网络请求吗?
不会。`PublicSuffix` 自带打包好的列表。它不会发起任何 HTTP 请求来解析或验证域名。
## 术语
- **TLD** (Top-Level Domain):域名的最后一段。例如,在 `mozilla.org` 中,`.org` 部分就是 TLD。
- **SLD** (Second-Level Domain):直接位于顶级域名下方的域名。例如,在 `https://www.mozilla.org/en-US/` 中,`mozilla` 就是 `.org` TLD 的二级域名。
- **TRD** (Third-Level Domain):也称为子域名,这是位于 SLD 或根域名之前的域名部分。例如,在 `https://www.mozilla.org/en-US/` 中,`www` 就是 TRD。
- **FQDN** (Fully Qualified Domain Name):完整的域名,包括主机名、域名和顶级域名,并以尾点结束。格式为 `[hostname].[domain].[tld].`(例如,`www.mozilla.org.`)。
## 文档
库文档可在 https://pkg.go.dev/github.com/weppos/publicsuffix-go/publicsuffix 获取。
## 安全与漏洞报告
有关我们安全政策的完整信息和详情,请访问 [`SECURITY.md`](SECURITY.md)。
## 更新日志
详情请查看 [CHANGELOG.md](CHANGELOG.md)。
## 许可证
Copyright (c) 2016-2026 Simone Carletti. [MIT License](LICENSE.txt)。
[Public Suffix List 来源](https://publicsuffix.org/list/) 受 Mozilla Public License, v. 2.0 条款约束。
标签:EVTX分析, Go, Ruby工具, SOC Prime, SYN扫描, 域名解析, 开发工具, 日志审计, 网络库