network-infra-utility 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +21 -0
- data/CHANGELOG.md +31 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +70 -0
- data/Rakefile +1 -1
- data/bin/dns-query +834 -0
- data/bin/geo-doc +135 -0
- data/bin/geo-get +1 -1
- data/document/ASNum/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +242 -0
- data/document/DNSQuery/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +248 -0
- data/document/Geo/345/221/275/344/273/244/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +441 -0
- data/document/IP/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +297 -0
- data/document/MAC/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +296 -0
- data/document/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/344/275/277/347/224/250/346/226/271/346/263/225.md +764 -0
- data/network-infra-utility.gemspec +4 -2
- data/network.rb +3 -1
- data/service/geodb/GeoAPI.md +1 -0
- data/service/geodb/geodb.rb +278 -1
- data/service/ssh/README.md +942 -0
- data/service/ssh/bin/ssh-client +198 -0
- data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/345/212/237/350/203/275/351/234/200/346/261/202/346/226/207/346/241/243.md +292 -0
- data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/257/246/347/273/206/350/256/276/350/256/241/346/226/207/346/241/243.md +1521 -0
- data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/275/257/344/273/266/350/256/276/350/256/241/346/226/207/346/241/243.md +2493 -0
- data/service/ssh/ext/ssh_core/bin/ssh_core.cmd +28 -0
- data/service/ssh/ext/ssh_core/config/sys.config +0 -0
- data/service/ssh/ext/ssh_core/config/vm.args +0 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM +1 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/LICENSE +21 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/README.md +696 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/VERSION +1 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz +0 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/metadata.config +15 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.config +17 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock +1 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src +10 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl +506 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl +393 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl +18 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl +81 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl +1909 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl +116 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl +1214 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl +408 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl +389 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl +121 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl +506 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl +393 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl +18 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl +81 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl +1909 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl +116 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl +1214 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl +408 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl +389 -0
- data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl +121 -0
- data/service/ssh/ext/ssh_core/rebar.config +24 -0
- data/service/ssh/ext/ssh_core/rebar.lock +1 -0
- data/service/ssh/ext/ssh_core/src/ssh_auth_engine.erl +156 -0
- data/service/ssh/ext/ssh_core/src/ssh_channel_stm.erl +232 -0
- data/service/ssh/ext/ssh_core/src/ssh_codec.erl +83 -0
- data/service/ssh/ext/ssh_core/src/ssh_conn_sup.erl +48 -0
- data/service/ssh/ext/ssh_core/src/ssh_conn_worker.erl +535 -0
- data/service/ssh/ext/ssh_core/src/ssh_core.app.src +36 -0
- data/service/ssh/ext/ssh_core/src/ssh_core_app.erl +11 -0
- data/service/ssh/ext/ssh_core/src/ssh_core_sup.erl +46 -0
- data/service/ssh/ext/ssh_core/src/ssh_infra_sup.erl +104 -0
- data/service/ssh/ext/ssh_core/src/ssh_ipc.hrl +80 -0
- data/service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl +94 -0
- data/service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl +467 -0
- data/service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl +95 -0
- data/service/ssh/ext/ssh_core/src/ssh_jump_chain.erl +101 -0
- data/service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl +222 -0
- data/service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl +67 -0
- data/service/ssh/ext/ssh_core/src/ssh_port_fwd.erl +225 -0
- data/service/ssh/ext/ssh_core/src/ssh_sftp_session.erl +250 -0
- data/service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl +62 -0
- data/service/ssh/ext/ssh_core_rs/Cargo.lock +2345 -0
- data/service/ssh/ext/ssh_core_rs/Cargo.toml +30 -0
- data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs +34 -0
- data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd +40 -0
- data/service/ssh/ext/ssh_core_rs/src/channel.rs +296 -0
- data/service/ssh/ext/ssh_core_rs/src/coalesce.rs +143 -0
- data/service/ssh/ext/ssh_core_rs/src/codec.rs +71 -0
- data/service/ssh/ext/ssh_core_rs/src/conn.rs +628 -0
- data/service/ssh/ext/ssh_core_rs/src/gateway.rs +389 -0
- data/service/ssh/ext/ssh_core_rs/src/handler.rs +293 -0
- data/service/ssh/ext/ssh_core_rs/src/keepalive.rs +194 -0
- data/service/ssh/ext/ssh_core_rs/src/main.rs +351 -0
- data/service/ssh/ext/ssh_core_rs/src/portfwd.rs +378 -0
- data/service/ssh/ext/ssh_core_rs/src/proto.rs +198 -0
- data/service/ssh/ext/ssh_core_rs/src/sftp.rs +294 -0
- data/service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb +213 -0
- data/service/ssh/lib/network_infra_utility/ssh/client.rb +257 -0
- data/service/ssh/lib/network_infra_utility/ssh/config/schema.rb +90 -0
- data/service/ssh/lib/network_infra_utility/ssh/config/settings.rb +103 -0
- data/service/ssh/lib/network_infra_utility/ssh/config/store.rb +90 -0
- data/service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb +83 -0
- data/service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb +36 -0
- data/service/ssh/lib/network_infra_utility/ssh/ipc/router.rb +212 -0
- data/service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb +81 -0
- data/service/ssh/lib/network_infra_utility/ssh/security/host_key.rb +211 -0
- data/service/ssh/lib/network_infra_utility/ssh/security/vault.rb +211 -0
- data/service/ssh/lib/network_infra_utility/ssh/session/history.rb +56 -0
- data/service/ssh/lib/network_infra_utility/ssh/session/manager.rb +92 -0
- data/service/ssh/lib/network_infra_utility/ssh/session/session.rb +109 -0
- data/service/ssh/lib/network_infra_utility/ssh/session/tree.rb +95 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb +435 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb +78 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb +159 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb +195 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb +212 -0
- data/service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb +127 -0
- data/service/ssh/lib/network_infra_utility/ssh/version.rb +7 -0
- data/service/ssh/lib/network_infra_utility/ssh.rb +44 -0
- data/support/basic/as_num.rb +221 -0
- data/support/basic/mac_address.rb +281 -0
- data/version.rb +1 -1
- metadata +138 -1
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
|
|
2
|
+
# Geo 命令工具使用方法
|
|
3
|
+
|
|
4
|
+
> 命令文件:`bin/geo-load` / `bin/geo-api` / `bin/geo-get`
|
|
5
|
+
> 安装方式:`gem install` 后三个命令自动进入 PATH,直接全局可用
|
|
6
|
+
|
|
7
|
+
三个命令构成完整工作流:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
geo-load (CSV→JSON) → geo-api (启动查询服务) → geo-get (查询 IP 归属)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 一、命令行用法
|
|
16
|
+
|
|
17
|
+
### 1. `geo-load` — GeoLite2 CSV 转 JSON
|
|
18
|
+
|
|
19
|
+
把 GeoLite2 解压后的 CSV 目录转换为 geo-api 可用的 JSON 数据文件。一次调用依次执行 ASN / City / Country 三类转换,生成 7 个 JSON 文件。
|
|
20
|
+
|
|
21
|
+
**用法:**
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
geo-load [RAW_DIR] [DOC_DIR] [options]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**参数:**
|
|
28
|
+
|
|
29
|
+
| 参数 | 说明 |
|
|
30
|
+
|------|------|
|
|
31
|
+
| `RAW_DIR` | GeoLite2 CSV 目录(可省,省则在当前目录查找) |
|
|
32
|
+
| `DOC_DIR` | JSON 输出目录(可省,省则输出到 `./geodb/`) |
|
|
33
|
+
|
|
34
|
+
**参数规则:**
|
|
35
|
+
|
|
36
|
+
- **RAW_DIR 不写**:在当前工作目录下递归查找 `GeoLite2-ASN-CSV_*` / `GeoLite2-City-CSV_*` / `GeoLite2-Country-CSV_*` 目录,找不到则报错退出
|
|
37
|
+
- **RAW_DIR 写了但路径不存在**:报错退出
|
|
38
|
+
- **DOC_DIR 不写**:在当前工作目录下生成 `geodb/` 子目录
|
|
39
|
+
- **DOC_DIR 写了但路径不存在**:自动创建该目录;创建不了则报错退出
|
|
40
|
+
- **DOC_DIR 写了且路径已存在**:直接往里写(覆盖同名文件)
|
|
41
|
+
|
|
42
|
+
**选项:**
|
|
43
|
+
|
|
44
|
+
| 选项 | 说明 |
|
|
45
|
+
|------|------|
|
|
46
|
+
| `--asn-only` | 仅转换 ASN 数据 |
|
|
47
|
+
| `--city-only` | 仅转换 City 数据 |
|
|
48
|
+
| `--country-only` | 仅转换 Country 数据 |
|
|
49
|
+
| `-h, --help` | 显示帮助 |
|
|
50
|
+
| `-v, --version` | 显示版本 |
|
|
51
|
+
|
|
52
|
+
不指定 `--*-only` 时三类全转。
|
|
53
|
+
|
|
54
|
+
**生成的文件:**
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
asn.json city-IPv4.json city-IPv6.json
|
|
58
|
+
country-IPv4.json country-IPv6.json
|
|
59
|
+
geo-city.json geo-country.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**示例:**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 当前目录下有 GeoLite2 CSV 解压包,输出到 ./geodb/
|
|
66
|
+
geo-load
|
|
67
|
+
|
|
68
|
+
# 指定 CSV 目录,输出到默认 ./geodb/
|
|
69
|
+
geo-load /data/GeoLite2-CSV
|
|
70
|
+
|
|
71
|
+
# 指定输入和输出
|
|
72
|
+
geo-load /data/GeoLite2-CSV /var/lib/geodb
|
|
73
|
+
|
|
74
|
+
# 只转 ASN(最轻量,约 30 秒)
|
|
75
|
+
geo-load /data/GeoLite2-CSV --asn-only
|
|
76
|
+
|
|
77
|
+
# 只转 Country
|
|
78
|
+
geo-load /data/GeoLite2-CSV --country-only
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**输出目录结构要求:**
|
|
82
|
+
|
|
83
|
+
RAW_DIR 期望包含以下子目录之一(或全部),每个子目录内含对应 CSV 文件:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
GeoLite2-ASN-CSV_*/
|
|
87
|
+
├── GeoLite2-ASN-Blocks-IPv4.csv
|
|
88
|
+
└── GeoLite2-ASN-Blocks-IPv6.csv
|
|
89
|
+
|
|
90
|
+
GeoLite2-City-CSV_*/
|
|
91
|
+
├── GeoLite2-City-Locations-zh-CN.csv
|
|
92
|
+
├── GeoLite2-City-Blocks-IPv4.csv
|
|
93
|
+
└── GeoLite2-City-Blocks-IPv6.csv
|
|
94
|
+
|
|
95
|
+
GeoLite2-Country-CSV_*/
|
|
96
|
+
├── GeoLite2-Country-Locations-zh-CN.csv
|
|
97
|
+
├── GeoLite2-Country-Blocks-IPv4.csv
|
|
98
|
+
└── GeoLite2-Country-Blocks-IPv6.csv
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
工具会递归扫描 RAW_DIR 下的 `**/GeoLite2-*-CSV_*/` 目录,不要求三类目录都在。
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### 2. `geo-api` — 启动 IP 归属查询服务
|
|
106
|
+
|
|
107
|
+
把 JSON 数据文件加载到内存,启动 HTTP 服务供 geo-get 或其他客户端查询。
|
|
108
|
+
|
|
109
|
+
**用法:**
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
geo-api [options]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**选项:**
|
|
116
|
+
|
|
117
|
+
| 选项 | 默认值 | 说明 |
|
|
118
|
+
|------|--------|------|
|
|
119
|
+
| `-d, --data-dir DIR` | `./geodb/` | JSON 数据文件目录(或环境变量 `GEODB_DATA_DIR`) |
|
|
120
|
+
| `-b, --host HOST` | `0.0.0.0` | 监听地址 |
|
|
121
|
+
| `-p, --port PORT` | `9292` | 监听端口 |
|
|
122
|
+
| `-s, --server NAME` | `puma` | Rack 服务器 |
|
|
123
|
+
| `-h, --help` | | 显示帮助 |
|
|
124
|
+
| `-v, --version` | | 显示版本 |
|
|
125
|
+
|
|
126
|
+
**启动前校验:** 目录不存在或目录下没有任何 `.json` 文件会直接报错退出。
|
|
127
|
+
|
|
128
|
+
**示例:**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# 默认配置(读取 ./geodb/,监听 0.0.0.0:9292)
|
|
132
|
+
geo-api
|
|
133
|
+
|
|
134
|
+
# 指定数据目录
|
|
135
|
+
geo-api -d /var/lib/geodb
|
|
136
|
+
|
|
137
|
+
# 指定数据和端口
|
|
138
|
+
geo-api -d /var/lib/geodb -p 8080
|
|
139
|
+
|
|
140
|
+
# 仅本机访问
|
|
141
|
+
geo-api -b 127.0.0.1 -d ./geodb
|
|
142
|
+
|
|
143
|
+
# 通过环境变量指定数据目录
|
|
144
|
+
GEODB_DATA_DIR=/data/geodb geo-api
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**HTTP 接口一览:**
|
|
148
|
+
|
|
149
|
+
| 接口 | 参数 | 说明 |
|
|
150
|
+
|------|------|------|
|
|
151
|
+
| `GET /` | 无 | 服务信息与接口清单 |
|
|
152
|
+
| `GET /geo/asn?num=XXX` | AS 编号 | 查该 AS 名下所有地址段 |
|
|
153
|
+
| `GET /geo/asn?addr=X.X.X.X` | IP 地址 | 按 IP 反查所属 AS |
|
|
154
|
+
| `GET /geo/city?id=XXX` | geoname_id | 查城市级定位信息 |
|
|
155
|
+
| `GET /geo/city?addr=X.X.X.X` | IP 地址 | 按 IP 查城市归属 |
|
|
156
|
+
| `GET /geo/country?id=XXX` | geoname_id | 查国别信息 |
|
|
157
|
+
| `GET /geo/country?addr=X.X.X.X` | IP 地址 | 按 IP 查国家归属 |
|
|
158
|
+
|
|
159
|
+
完整接口文档见 `service/geodb/GeoAPI.md`。
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### 3. `geo-get` — 查询单个 IP 的归属信息
|
|
164
|
+
|
|
165
|
+
向运行中的 geo-api 服务发起查询,一次输入 IP,同时拉取 country / city / asn 三类信息并汇总输出。
|
|
166
|
+
|
|
167
|
+
**用法:**
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
geo-get [IP] [options]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**选项:**
|
|
174
|
+
|
|
175
|
+
| 选项 | 说明 |
|
|
176
|
+
|------|------|
|
|
177
|
+
| `-t, --text` | 文字格式输出(默认) |
|
|
178
|
+
| `-j, --json` | JSON 格式输出 |
|
|
179
|
+
| `--country` | 仅查询国家接口 |
|
|
180
|
+
| `--city` | 仅查询城市接口 |
|
|
181
|
+
| `--asn` | 仅查询 ASN 接口 |
|
|
182
|
+
| `-h, --help` | 显示帮助 |
|
|
183
|
+
| `-v, --version` | 显示版本 |
|
|
184
|
+
|
|
185
|
+
不指定 `--country` / `--city` / `--asn` 时三接口齐查。不指定 IP 时用默认演示 IP `1.181.240.251`。
|
|
186
|
+
|
|
187
|
+
默认连 `http://127.0.0.1:9292`(geo-api 默认监听)。服务未运行时给出提示与启动命令。
|
|
188
|
+
|
|
189
|
+
**示例:**
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# 默认:三接口齐查,文字格式
|
|
193
|
+
geo-get 1.181.240.251
|
|
194
|
+
|
|
195
|
+
# JSON 格式(适合管道处理)
|
|
196
|
+
geo-get 8.8.8.8 -j
|
|
197
|
+
|
|
198
|
+
# 仅查 ASN
|
|
199
|
+
geo-get 8.8.8.8 --asn
|
|
200
|
+
|
|
201
|
+
# 仅查国家,JSON 格式
|
|
202
|
+
geo-get 1.1.1.1 --country --json
|
|
203
|
+
|
|
204
|
+
# 不给 IP,用默认演示 IP
|
|
205
|
+
geo-get
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**文字格式输出示例:**
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
查询 IP: 1.181.240.251 范围: country / city / asn 三接口齐查 服务: http://127.0.0.1:9292
|
|
212
|
+
------------------------------------------------------------
|
|
213
|
+
1.181.240.251 的归属信息:
|
|
214
|
+
[国家] 中国 (CN) 网段 1.180.0.0/14
|
|
215
|
+
[城市] 未知 坐标 无 网段 1.180.0.0/14
|
|
216
|
+
[ASN] AS4134 Chinanet 网段 1.180.0.0/15
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**JSON 格式输出示例:**
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"country": { ... },
|
|
224
|
+
"city": { ... },
|
|
225
|
+
"asn": { ... }
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
某个接口未命中(404)时,JSON 中对应字段为 `null`,不逐条报错。三个接口全未命中时,文字格式给一行提示。
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### 完整工作流示例
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# 1. 下载 GeoLite2 CSV 包并解压
|
|
237
|
+
cd /data
|
|
238
|
+
tar xzf GeoLite2-CSV.zip
|
|
239
|
+
|
|
240
|
+
# 2. 转换为 JSON(当前目录找 CSV,输出到 ./geodb/)
|
|
241
|
+
geo-load
|
|
242
|
+
|
|
243
|
+
# 3. 启动查询服务
|
|
244
|
+
geo-api -d ./geodb -p 9292 &
|
|
245
|
+
|
|
246
|
+
# 4. 另一个终端查询
|
|
247
|
+
geo-get 8.8.8.8
|
|
248
|
+
geo-get 1.1.1.1 -j
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 二、代码级用法
|
|
254
|
+
|
|
255
|
+
### 1. GeoDB 模块 — CSV 加载(对应 geo-load)
|
|
256
|
+
|
|
257
|
+
> 源码位置:`service/geodb/geodb.rb`
|
|
258
|
+
> 加载方式:`require 'network'` 后 `require 'geodb'`
|
|
259
|
+
|
|
260
|
+
三个模块方法,各自处理一类数据,均可单独调用:
|
|
261
|
+
|
|
262
|
+
```ruby
|
|
263
|
+
require 'network'
|
|
264
|
+
require 'geodb'
|
|
265
|
+
|
|
266
|
+
# 把 GeoLite2 ASN CSV 转成 asn.json
|
|
267
|
+
# 第一个参数: CSV glob 模式 (相对调用目录或绝对路径)
|
|
268
|
+
# 第二个参数: 输出目录 (必须以 / 结尾)
|
|
269
|
+
GeoDB.load_asn(
|
|
270
|
+
'/data/GeoLite2-ASN-CSV_20260725/*.csv',
|
|
271
|
+
'/var/lib/geodb/'
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
# City: 生成 geo-city.json + city-IPv4.json + city-IPv6.json
|
|
275
|
+
# 内部按文件名 Location-zh-CN / Blocks-IPv4 / Blocks-IPv6 分流
|
|
276
|
+
GeoDB.load_city(
|
|
277
|
+
'/data/GeoLite2-City-CSV_20260724/*.csv',
|
|
278
|
+
'/var/lib/geodb/'
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Country: 生成 geo-country.json + country-IPv4.json + country-IPv6.json
|
|
282
|
+
GeoDB.load_country(
|
|
283
|
+
'/data/GeoLite2-Country-CSV_20260724/*.csv',
|
|
284
|
+
'/var/lib/geodb/'
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**方法签名:**
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
GeoDB.load_asn(dir_path, out_path) → Hash { range => record }
|
|
292
|
+
GeoDB.load_city(dir_path, out_path) → [city_Hash, geo_Hash]
|
|
293
|
+
GeoDB.load_country(dir_path, out_path) → [country_Hash, geo_Hash]
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**JSON 键格式(范围型):**
|
|
297
|
+
|
|
298
|
+
geodb.rb 把 CIDR 通过 `IP.range` 展开为 `[start_num, end_num]`,作为 JSON 的键:
|
|
299
|
+
|
|
300
|
+
```ruby
|
|
301
|
+
# CSV 中的 network 字段 "1.0.4.0/22"
|
|
302
|
+
# 转换后 JSON 键为 Ruby 数组序列化字符串:
|
|
303
|
+
# "[16777984, 16778239]"
|
|
304
|
+
# 值为原始 CSV 记录 (行头映射的 Hash)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**内部实现要点:**
|
|
308
|
+
|
|
309
|
+
- `Dir[glob]` 匹配 CSV 文件,多个文件依次处理
|
|
310
|
+
- `CSV.parse File.read(path)` 读入后用 `table.first` 作表头,`mapping` 方法把每行映射为 `{列名=>值}` 的 Hash
|
|
311
|
+
- `IP.range(record['network'])` 把 CIDR 展开为 `[start_ip, end_ip]`,再 `.map(&:number)` 转整数
|
|
312
|
+
- City / Country 的 Locations 文件单独提取为 geo 表(按 `geoname_id` 索引),Blocks 文件按 IPv4/IPv6 分两份输出
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### 2. GeoAPI 服务 — 启动与接口(对应 geo-api)
|
|
317
|
+
|
|
318
|
+
> 源码位置:`service/geodb/api.rb`
|
|
319
|
+
> 加载方式:`require 'network'` 后 `require 'api'`(需把 `service/geodb` 加入 `$LOAD_PATH`)
|
|
320
|
+
|
|
321
|
+
#### 启动服务
|
|
322
|
+
|
|
323
|
+
```ruby
|
|
324
|
+
require 'network'
|
|
325
|
+
$LOAD_PATH.unshift File.join(__dir__, 'service', 'geodb')
|
|
326
|
+
require 'api'
|
|
327
|
+
|
|
328
|
+
ENV['GEODB_DATA_DIR'] = '/var/lib/geodb' # 指定数据目录
|
|
329
|
+
|
|
330
|
+
require 'rackup'
|
|
331
|
+
Rackup::Server.start(
|
|
332
|
+
app: GeoAPI.app,
|
|
333
|
+
server: 'puma',
|
|
334
|
+
Host: '0.0.0.0',
|
|
335
|
+
Port: 9292
|
|
336
|
+
)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### GeoDB 模块方法(接口内部逻辑,也可代码调用)
|
|
340
|
+
|
|
341
|
+
```ruby
|
|
342
|
+
# 数据目录 (读 ENV['GEODB_DATA_DIR'], 默认 ./geodb/)
|
|
343
|
+
GeoDB.data_dir # => "/var/lib/geodb/"
|
|
344
|
+
|
|
345
|
+
# ASN 查询
|
|
346
|
+
GeoDB.asn_by_num('13335') # 该 AS 名下所有地址段 (走反向索引, O(1))
|
|
347
|
+
GeoDB.asn_by_addr('1.0.0.5') # 按 IP 查所属 AS → record 或 nil 或 :invalid
|
|
348
|
+
|
|
349
|
+
# City 查询
|
|
350
|
+
GeoDB.city_by_id('1814991') # 按 geoname_id 查 → record / nil / :invalid
|
|
351
|
+
GeoDB.city_by_addr('1.0.1.1') # 按 IP 查 → enriched record / nil / :invalid
|
|
352
|
+
|
|
353
|
+
# Country 查询
|
|
354
|
+
GeoDB.country_by_id('6252001') # 按 geoname_id 查
|
|
355
|
+
GeoDB.country_by_addr('1.0.1.1') # 按 IP 查
|
|
356
|
+
|
|
357
|
+
# 预热 (后台异步加载, 避免首次查询卡顿)
|
|
358
|
+
GeoDB.preload('asn', 'country-IPv4', 'country-IPv6')
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**返回值约定:**
|
|
362
|
+
|
|
363
|
+
| 场景 | 返回 |
|
|
364
|
+
|------|------|
|
|
365
|
+
| IP 不合法 | `:invalid` |
|
|
366
|
+
| 无结果 | `nil` |
|
|
367
|
+
| 命中 | 纯 Record (Hash) 或 enrich 后的 Hash(含 `geoname` / `registered_country` 嵌套对象) |
|
|
368
|
+
|
|
369
|
+
#### enrich 关联机制
|
|
370
|
+
|
|
371
|
+
`city_by_addr` / `country_by_addr` 命中后会调用 `enrich`,把范围记录里的三个 geoname_id 外键关联到 geo 表:
|
|
372
|
+
|
|
373
|
+
```ruby
|
|
374
|
+
record = {
|
|
375
|
+
'network' => '1.0.1.0/24',
|
|
376
|
+
'geoname_id' => '1814991',
|
|
377
|
+
'registered_country_geoname_id' => '1814991',
|
|
378
|
+
'represented_country_geoname_id' => nil,
|
|
379
|
+
...
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
GeoDB.enrich(record, 'geo-city')
|
|
383
|
+
# => {
|
|
384
|
+
# ...原字段...,
|
|
385
|
+
# 'geoname' => { geoname_id, country_name, city_name, ... },
|
|
386
|
+
# 'registered_country' => { ... },
|
|
387
|
+
# 'represented_country' => nil
|
|
388
|
+
# }
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### 加载与缓存机制
|
|
392
|
+
|
|
393
|
+
- 范围型 JSON(`asn` / `city-IPv4` 等)首次访问时全量加载、按 start 排序、缓存到 `@store`,后续走内存二分
|
|
394
|
+
- ASN 额外建 `@asn_index` 反向索引(`as_number → [record...]`),`num` 查询 O(1)
|
|
395
|
+
- 地理型 JSON(`geo-city` / `geo-country`)缓存为扁平 Hash,按 `geoname_id` 字符串键取值
|
|
396
|
+
- 文件缺失时 `@store[name] = nil`,对应接口返回 404 `无结果`,不影响其他接口
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### 3. geo-get 的查询逻辑(HTTP 客户端代码)
|
|
401
|
+
|
|
402
|
+
> 源码位置:`bin/geo-get`
|
|
403
|
+
> geo-get 是纯 HTTP 客户端,不加载 GeoDB 模块,不依赖数据文件
|
|
404
|
+
|
|
405
|
+
```ruby
|
|
406
|
+
require 'net/http'
|
|
407
|
+
require 'json'
|
|
408
|
+
|
|
409
|
+
BASE = 'http://127.0.0.1:9292'
|
|
410
|
+
|
|
411
|
+
# 发起一次 GET, 返回 {code:, body:}
|
|
412
|
+
def fetch(base, path, params)
|
|
413
|
+
uri = URI("#{base}#{path}")
|
|
414
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
|
415
|
+
res = Net::HTTP.get_response(uri)
|
|
416
|
+
{ code: res.code.to_i, body: (JSON.parse(res.body) rescue res.body) }
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# 三接口齐查
|
|
420
|
+
results = {}
|
|
421
|
+
results[:country] = fetch(BASE, '/geo/country', addr: '8.8.8.8')
|
|
422
|
+
results[:city] = fetch(BASE, '/geo/city', addr: '8.8.8.8')
|
|
423
|
+
results[:asn] = fetch(BASE, '/geo/asn', addr: '8.8.8.8')
|
|
424
|
+
|
|
425
|
+
# 命中提取
|
|
426
|
+
results.each do |key, r|
|
|
427
|
+
puts key if r[:code] == 200
|
|
428
|
+
end
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**查询顺序与错误处理:**
|
|
432
|
+
|
|
433
|
+
1. 依次(非并行)请求 country → city → asn 三个接口
|
|
434
|
+
2. 每个接口返回 200 时收集命中数据,404/400 等静默跳过
|
|
435
|
+
3. 三个接口全部未命中时统一输出一行提示,不逐条刷 404
|
|
436
|
+
4. 连接被拒(`Errno::ECONNREFUSED`)时直接 abort 并提示启动命令
|
|
437
|
+
|
|
438
|
+
**文字格式 vs JSON 格式:**
|
|
439
|
+
|
|
440
|
+
- 文字格式:从响应体中提取关键字段(国家名、城市名、ASN 组织、网段等)拼成可读行
|
|
441
|
+
- JSON 格式:把三个接口的响应体原样放进 `{country:, city:, asn:}` 结构,未命中的字段为 `null`,用 `JSON.pretty_generate` 输出
|