mirror of
https://github.com/zu1k/nali.git
synced 2025-02-09 05:42:43 +08:00
add ipv6 test
This commit is contained in:
parent
a3b7e78111
commit
6b4ee442d7
6
pkg/common/const.go
Normal file
6
pkg/common/const.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
const (
|
||||||
|
RedirectMode1 = 0x01 // one mode
|
||||||
|
RedirectMode2 = 0x02 //another mode
|
||||||
|
)
|
9
pkg/common/dbtool.go
Normal file
9
pkg/common/dbtool.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
// byteToUInt32 将 byte 转换为uint32
|
||||||
|
func ByteToUInt32(data []byte) uint32 {
|
||||||
|
i := uint32(data[0]) & 0xff
|
||||||
|
i |= (uint32(data[1]) << 8) & 0xff00
|
||||||
|
i |= (uint32(data[2]) << 16) & 0xff0000
|
||||||
|
return i
|
||||||
|
}
|
84
pkg/common/struct.go
Normal file
84
pkg/common/struct.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// FileInfo: info of db file
|
||||||
|
type FileInfo struct {
|
||||||
|
Data []byte
|
||||||
|
FilePath string
|
||||||
|
FileBase *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPDB common ip database
|
||||||
|
type IPDB struct {
|
||||||
|
Data *FileInfo
|
||||||
|
Offset uint32
|
||||||
|
ItemLen uint32
|
||||||
|
IndexLen uint32
|
||||||
|
IPNum uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// setOffset 设置偏移量
|
||||||
|
func (db *IPDB) SetOffset(offset uint32) {
|
||||||
|
db.Offset = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
// readString 获取字符串
|
||||||
|
func (db *IPDB) ReadString(offset uint32) []byte {
|
||||||
|
db.SetOffset(offset)
|
||||||
|
data := make([]byte, 0, 30)
|
||||||
|
buf := make([]byte, 1)
|
||||||
|
for {
|
||||||
|
buf = db.ReadData(1)
|
||||||
|
if buf[0] == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data = append(data, buf[0])
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// readData 从文件中读取数据
|
||||||
|
func (db *IPDB) ReadData(length int, offset ...uint32) (rs []byte) {
|
||||||
|
if len(offset) > 0 {
|
||||||
|
db.SetOffset(offset[0])
|
||||||
|
}
|
||||||
|
readLength := uint32(length)
|
||||||
|
end := db.Offset + readLength
|
||||||
|
dataNum := uint32(len(db.Data.Data))
|
||||||
|
if db.Offset > dataNum {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if end > dataNum {
|
||||||
|
end = dataNum
|
||||||
|
}
|
||||||
|
rs = db.Data.Data[db.Offset:end]
|
||||||
|
db.Offset = end
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// readMode 获取偏移值类型
|
||||||
|
func (db *IPDB) ReadMode(offset uint32) byte {
|
||||||
|
mode := db.ReadData(1, offset)
|
||||||
|
return mode[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadUInt24
|
||||||
|
func (db *IPDB) ReadUInt24() uint32 {
|
||||||
|
buf := db.ReadData(3)
|
||||||
|
return ByteToUInt32(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readArea 读取区域
|
||||||
|
func (db *IPDB) ReadArea(offset uint32) []byte {
|
||||||
|
mode := db.ReadMode(offset)
|
||||||
|
if mode == RedirectMode1 || mode == RedirectMode2 {
|
||||||
|
areaOffset := db.ReadUInt24()
|
||||||
|
if areaOffset == 0 {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
return db.ReadString(areaOffset)
|
||||||
|
}
|
||||||
|
return db.ReadString(offset)
|
||||||
|
}
|
@ -9,33 +9,22 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zu1k/nali/pkg/common"
|
||||||
"golang.org/x/text/encoding/simplifiedchinese"
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
)
|
)
|
||||||
|
|
||||||
// db file info with data
|
|
||||||
type FileInfo struct {
|
|
||||||
Data []byte
|
|
||||||
FilePath string
|
|
||||||
FileBase *os.File
|
|
||||||
IPNum int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// qq ip db
|
|
||||||
type QQwry struct {
|
|
||||||
data *FileInfo
|
|
||||||
offset int64
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IndexLen = 7 // index length
|
IndexLen = 7 // index length
|
||||||
RedirectMode1 = 0x01 // one mode
|
|
||||||
RedirectMode2 = 0x02 //another mode
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type QQwry struct {
|
||||||
|
common.IPDB
|
||||||
|
}
|
||||||
|
|
||||||
// new db from path
|
// new db from path
|
||||||
func NewQQwry(filePath string) QQwry {
|
func NewQQwry(filePath string) common.IPDB {
|
||||||
var tmpData []byte
|
var tmpData []byte
|
||||||
var fileInfo FileInfo
|
var fileInfo common.FileInfo
|
||||||
|
|
||||||
// 判断文件是否存在
|
// 判断文件是否存在
|
||||||
_, err := os.Stat(filePath)
|
_, err := os.Stat(filePath)
|
||||||
@ -69,24 +58,21 @@ func NewQQwry(filePath string) QQwry {
|
|||||||
start := binary.LittleEndian.Uint32(buf[:4])
|
start := binary.LittleEndian.Uint32(buf[:4])
|
||||||
end := binary.LittleEndian.Uint32(buf[4:])
|
end := binary.LittleEndian.Uint32(buf[4:])
|
||||||
|
|
||||||
fileInfo.IPNum = int64((end-start)/IndexLen + 1)
|
return common.IPDB{
|
||||||
|
Data: &fileInfo,
|
||||||
return QQwry{
|
IPNum: uint32((end-start)/IndexLen + 1),
|
||||||
data: &fileInfo,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setOffset 设置偏移量
|
|
||||||
func (q *QQwry) setOffset(offset int64) {
|
|
||||||
q.offset = offset
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find ip地址查询对应归属地信息
|
// Find ip地址查询对应归属地信息
|
||||||
func (q QQwry) Find(ip string) (res string) {
|
func (q QQwry) Find(ip string) (res string) {
|
||||||
if strings.Count(ip, ".") != 3 {
|
if strings.Count(ip, ".") != 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
offset := q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
|
|
||||||
|
ip4 := binary.BigEndian.Uint32(net.ParseIP(ip).To4())
|
||||||
|
|
||||||
|
offset := q.searchIndex(ip4)
|
||||||
if offset <= 0 {
|
if offset <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -94,26 +80,26 @@ func (q QQwry) Find(ip string) (res string) {
|
|||||||
var gbkCountry []byte
|
var gbkCountry []byte
|
||||||
var gbkArea []byte
|
var gbkArea []byte
|
||||||
|
|
||||||
mode := q.readMode(offset + 4)
|
mode := q.ReadMode(offset + 4)
|
||||||
if mode == RedirectMode1 {
|
if mode == common.RedirectMode1 {
|
||||||
countryOffset := q.readUInt24()
|
countryOffset := q.ReadUInt24()
|
||||||
mode = q.readMode(countryOffset)
|
mode = q.ReadMode(countryOffset)
|
||||||
if mode == RedirectMode2 {
|
if mode == common.RedirectMode2 {
|
||||||
c := q.readUInt24()
|
c := q.ReadUInt24()
|
||||||
gbkCountry = q.readString(c)
|
gbkCountry = q.ReadString(c)
|
||||||
countryOffset += 4
|
countryOffset += 4
|
||||||
} else {
|
} else {
|
||||||
gbkCountry = q.readString(countryOffset)
|
gbkCountry = q.ReadString(countryOffset)
|
||||||
countryOffset += uint32(len(gbkCountry) + 1)
|
countryOffset += uint32(len(gbkCountry) + 1)
|
||||||
}
|
}
|
||||||
gbkArea = q.readArea(countryOffset)
|
gbkArea = q.ReadArea(countryOffset)
|
||||||
} else if mode == RedirectMode2 {
|
} else if mode == common.RedirectMode2 {
|
||||||
countryOffset := q.readUInt24()
|
countryOffset := q.ReadUInt24()
|
||||||
gbkCountry = q.readString(countryOffset)
|
gbkCountry = q.ReadString(countryOffset)
|
||||||
gbkArea = q.readArea(offset + 8)
|
gbkArea = q.ReadArea(offset + 8)
|
||||||
} else {
|
} else {
|
||||||
gbkCountry = q.readString(offset + 4)
|
gbkCountry = q.ReadString(offset + 4)
|
||||||
gbkArea = q.readArea(offset + uint32(5+len(gbkCountry)))
|
gbkArea = q.ReadArea(offset + uint32(5+len(gbkCountry)))
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := simplifiedchinese.GBK.NewDecoder()
|
enc := simplifiedchinese.GBK.NewDecoder()
|
||||||
@ -123,43 +109,9 @@ func (q QQwry) Find(ip string) (res string) {
|
|||||||
return fmt.Sprintf("%s %s", country, area)
|
return fmt.Sprintf("%s %s", country, area)
|
||||||
}
|
}
|
||||||
|
|
||||||
// readMode 获取偏移值类型
|
|
||||||
func (q *QQwry) readMode(offset uint32) byte {
|
|
||||||
mode := q.readData(1, int64(offset))
|
|
||||||
return mode[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// readArea 读取区域
|
|
||||||
func (q *QQwry) readArea(offset uint32) []byte {
|
|
||||||
mode := q.readMode(offset)
|
|
||||||
if mode == RedirectMode1 || mode == RedirectMode2 {
|
|
||||||
areaOffset := q.readUInt24()
|
|
||||||
if areaOffset == 0 {
|
|
||||||
return []byte("")
|
|
||||||
}
|
|
||||||
return q.readString(areaOffset)
|
|
||||||
}
|
|
||||||
return q.readString(offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// readString 获取字符串
|
|
||||||
func (q *QQwry) readString(offset uint32) []byte {
|
|
||||||
q.setOffset(int64(offset))
|
|
||||||
data := make([]byte, 0, 30)
|
|
||||||
buf := make([]byte, 1)
|
|
||||||
for {
|
|
||||||
buf = q.readData(1)
|
|
||||||
if buf[0] == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
data = append(data, buf[0])
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// searchIndex 查找索引位置
|
// searchIndex 查找索引位置
|
||||||
func (q *QQwry) searchIndex(ip uint32) uint32 {
|
func (q *QQwry) searchIndex(ip uint32) uint32 {
|
||||||
header := q.readData(8, 0)
|
header := q.ReadData(8, 0)
|
||||||
|
|
||||||
start := binary.LittleEndian.Uint32(header[:4])
|
start := binary.LittleEndian.Uint32(header[:4])
|
||||||
end := binary.LittleEndian.Uint32(header[4:])
|
end := binary.LittleEndian.Uint32(header[4:])
|
||||||
@ -170,12 +122,12 @@ func (q *QQwry) searchIndex(ip uint32) uint32 {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
mid = q.getMiddleOffset(start, end)
|
mid = q.getMiddleOffset(start, end)
|
||||||
buf = q.readData(IndexLen, int64(mid))
|
buf = q.ReadData(IndexLen, mid)
|
||||||
_ip = binary.LittleEndian.Uint32(buf[:4])
|
_ip = binary.LittleEndian.Uint32(buf[:4])
|
||||||
|
|
||||||
if end-start == IndexLen {
|
if end-start == IndexLen {
|
||||||
offset := byteToUInt32(buf[4:])
|
offset := common.ByteToUInt32(buf[4:])
|
||||||
buf = q.readData(IndexLen)
|
buf = q.ReadData(IndexLen)
|
||||||
if ip < binary.LittleEndian.Uint32(buf[:4]) {
|
if ip < binary.LittleEndian.Uint32(buf[:4]) {
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
@ -188,47 +140,13 @@ func (q *QQwry) searchIndex(ip uint32) uint32 {
|
|||||||
} else if _ip < ip { // 找到的比较小,向后移
|
} else if _ip < ip { // 找到的比较小,向后移
|
||||||
start = mid
|
start = mid
|
||||||
} else if _ip == ip {
|
} else if _ip == ip {
|
||||||
return byteToUInt32(buf[4:])
|
return common.ByteToUInt32(buf[4:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// readUInt24
|
|
||||||
func (q *QQwry) readUInt24() uint32 {
|
|
||||||
buf := q.readData(3)
|
|
||||||
return byteToUInt32(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getMiddleOffset
|
// getMiddleOffset
|
||||||
func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 {
|
func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 {
|
||||||
records := ((end - start) / IndexLen) >> 1
|
records := ((end - start) / IndexLen) >> 1
|
||||||
return start + records*IndexLen
|
return start + records*IndexLen
|
||||||
}
|
}
|
||||||
|
|
||||||
// byteToUInt32 将 byte 转换为uint32
|
|
||||||
func byteToUInt32(data []byte) uint32 {
|
|
||||||
i := uint32(data[0]) & 0xff
|
|
||||||
i |= (uint32(data[1]) << 8) & 0xff00
|
|
||||||
i |= (uint32(data[2]) << 16) & 0xff0000
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
// readData 从文件中读取数据
|
|
||||||
func (q *QQwry) readData(num int, offset ...int64) (rs []byte) {
|
|
||||||
if len(offset) > 0 {
|
|
||||||
q.setOffset(offset[0])
|
|
||||||
}
|
|
||||||
nums := int64(num)
|
|
||||||
end := q.offset + nums
|
|
||||||
dataNum := int64(len(q.data.Data))
|
|
||||||
if q.offset > dataNum {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if end > dataNum {
|
|
||||||
end = dataNum
|
|
||||||
}
|
|
||||||
rs = q.data.Data[q.offset:end]
|
|
||||||
q.offset = end
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
129
pkg/zxipv6wry/zxipv6wry.go
Normal file
129
pkg/zxipv6wry/zxipv6wry.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package zxipv6wry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/zu1k/nali/pkg/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
header []byte
|
||||||
|
v6ip uint64
|
||||||
|
offset uint32
|
||||||
|
start uint32
|
||||||
|
end uint32
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZXwry struct {
|
||||||
|
common.IPDB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ZXwry) Find(ip string) (result string) {
|
||||||
|
q.Offset = 0
|
||||||
|
|
||||||
|
tp := big.NewInt(0)
|
||||||
|
op := big.NewInt(0)
|
||||||
|
tp.SetBytes(net.ParseIP(ip).To16())
|
||||||
|
op.SetString("18446744073709551616", 10)
|
||||||
|
op.Div(tp, op)
|
||||||
|
tp.SetString("FFFFFFFFFFFFFFFF", 16)
|
||||||
|
op.And(op, tp)
|
||||||
|
|
||||||
|
v6ip = op.Uint64()
|
||||||
|
offset = q.searchIndexV6(v6ip)
|
||||||
|
|
||||||
|
country, area := q.getAddr(offset)
|
||||||
|
|
||||||
|
if area == "ZX" {
|
||||||
|
area = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s %s", country, area)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ZXwry) getAddr(offset uint32) (string, string) {
|
||||||
|
mode := q.ReadMode(offset)
|
||||||
|
if mode == 0x01 {
|
||||||
|
// [IP][0x01][国家和地区信息的绝对偏移地址]
|
||||||
|
offset = q.ReadUInt24()
|
||||||
|
return q.getAddr(offset)
|
||||||
|
}
|
||||||
|
// [IP][0x02][信息的绝对偏移][...] or [IP][国家][...]
|
||||||
|
_offset := q.Offset - 1
|
||||||
|
c1 := q.ReadArea(_offset)
|
||||||
|
if mode == 0x02 {
|
||||||
|
q.Offset = 4 + _offset
|
||||||
|
} else {
|
||||||
|
q.Offset = _offset + uint32(1+len(c1))
|
||||||
|
}
|
||||||
|
c2 := q.ReadArea(q.Offset)
|
||||||
|
return string(c1), string(c2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ZXwry) searchIndexV4(ip uint32) uint32 {
|
||||||
|
q.ItemLen = 4
|
||||||
|
q.IndexLen = 7
|
||||||
|
header = q.Data.Data[0:8]
|
||||||
|
start = binary.LittleEndian.Uint32(header[:4])
|
||||||
|
end = binary.LittleEndian.Uint32(header[4:])
|
||||||
|
|
||||||
|
buf := make([]byte, q.IndexLen)
|
||||||
|
|
||||||
|
for {
|
||||||
|
mid := start + q.IndexLen*(((end-start)/q.IndexLen)>>1)
|
||||||
|
buf = q.Data.Data[mid : mid+q.IndexLen]
|
||||||
|
_ip := binary.LittleEndian.Uint32(buf[:q.ItemLen])
|
||||||
|
|
||||||
|
if end-start == q.IndexLen {
|
||||||
|
if ip >= binary.LittleEndian.Uint32(q.Data.Data[end:end+q.ItemLen]) {
|
||||||
|
buf = q.Data.Data[end : end+q.IndexLen]
|
||||||
|
}
|
||||||
|
return common.ByteToUInt32(buf[q.ItemLen:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if _ip > ip {
|
||||||
|
end = mid
|
||||||
|
} else if _ip < ip {
|
||||||
|
start = mid
|
||||||
|
} else if _ip == ip {
|
||||||
|
return common.ByteToUInt32(buf[q.ItemLen:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ZXwry) searchIndexV6(ip uint64) uint32 {
|
||||||
|
|
||||||
|
q.ItemLen = 8
|
||||||
|
q.IndexLen = 11
|
||||||
|
|
||||||
|
header = q.Data.Data[8:24]
|
||||||
|
start = binary.LittleEndian.Uint32(header[8:])
|
||||||
|
counts := binary.LittleEndian.Uint32(header[:8])
|
||||||
|
end = start + counts*q.IndexLen
|
||||||
|
|
||||||
|
buf := make([]byte, q.IndexLen)
|
||||||
|
|
||||||
|
for {
|
||||||
|
mid := start + q.IndexLen*(((end-start)/q.IndexLen)>>1)
|
||||||
|
buf = q.Data.Data[mid : mid+q.IndexLen]
|
||||||
|
_ip := binary.LittleEndian.Uint64(buf[:q.ItemLen])
|
||||||
|
|
||||||
|
if end-start == q.IndexLen {
|
||||||
|
if ip >= binary.LittleEndian.Uint64(q.Data.Data[end:end+q.ItemLen]) {
|
||||||
|
buf = q.Data.Data[end : end+q.IndexLen]
|
||||||
|
}
|
||||||
|
return common.ByteToUInt32(buf[q.ItemLen:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if _ip > ip {
|
||||||
|
end = mid
|
||||||
|
} else if _ip < ip {
|
||||||
|
start = mid
|
||||||
|
} else if _ip == ip {
|
||||||
|
return common.ByteToUInt32(buf[q.ItemLen:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user