binary.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. package srs
  2. import (
  3. "bufio"
  4. "compress/zlib"
  5. "encoding/binary"
  6. "io"
  7. "net/netip"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/option"
  10. "github.com/sagernet/sing/common"
  11. "github.com/sagernet/sing/common/domain"
  12. E "github.com/sagernet/sing/common/exceptions"
  13. "github.com/sagernet/sing/common/varbin"
  14. "go4.org/netipx"
  15. )
  16. var MagicBytes = [3]byte{0x53, 0x52, 0x53} // SRS
  17. const (
  18. ruleItemQueryType uint8 = iota
  19. ruleItemNetwork
  20. ruleItemDomain
  21. ruleItemDomainKeyword
  22. ruleItemDomainRegex
  23. ruleItemSourceIPCIDR
  24. ruleItemIPCIDR
  25. ruleItemSourcePort
  26. ruleItemSourcePortRange
  27. ruleItemPort
  28. ruleItemPortRange
  29. ruleItemProcessName
  30. ruleItemProcessPath
  31. ruleItemPackageName
  32. ruleItemWIFISSID
  33. ruleItemWIFIBSSID
  34. ruleItemFinal uint8 = 0xFF
  35. )
  36. func Read(reader io.Reader, recover bool) (ruleSet option.PlainRuleSet, err error) {
  37. var magicBytes [3]byte
  38. _, err = io.ReadFull(reader, magicBytes[:])
  39. if err != nil {
  40. return
  41. }
  42. if magicBytes != MagicBytes {
  43. err = E.New("invalid sing-box rule-set file")
  44. return
  45. }
  46. var version uint8
  47. err = binary.Read(reader, binary.BigEndian, &version)
  48. if err != nil {
  49. return ruleSet, err
  50. }
  51. if version > C.RuleSetVersion2 {
  52. return ruleSet, E.New("unsupported version: ", version)
  53. }
  54. compressReader, err := zlib.NewReader(reader)
  55. if err != nil {
  56. return
  57. }
  58. bReader := bufio.NewReader(compressReader)
  59. length, err := binary.ReadUvarint(bReader)
  60. if err != nil {
  61. return
  62. }
  63. ruleSet.Rules = make([]option.HeadlessRule, length)
  64. for i := uint64(0); i < length; i++ {
  65. ruleSet.Rules[i], err = readRule(bReader, recover)
  66. if err != nil {
  67. err = E.Cause(err, "read rule[", i, "]")
  68. return
  69. }
  70. }
  71. return
  72. }
  73. func Write(writer io.Writer, ruleSet option.PlainRuleSet, generateUnstable bool) error {
  74. _, err := writer.Write(MagicBytes[:])
  75. if err != nil {
  76. return err
  77. }
  78. var version uint8
  79. if generateUnstable {
  80. version = C.RuleSetVersion2
  81. } else {
  82. version = C.RuleSetVersion1
  83. }
  84. err = binary.Write(writer, binary.BigEndian, version)
  85. if err != nil {
  86. return err
  87. }
  88. compressWriter, err := zlib.NewWriterLevel(writer, zlib.BestCompression)
  89. if err != nil {
  90. return err
  91. }
  92. bWriter := bufio.NewWriter(compressWriter)
  93. _, err = varbin.WriteUvarint(bWriter, uint64(len(ruleSet.Rules)))
  94. if err != nil {
  95. return err
  96. }
  97. for _, rule := range ruleSet.Rules {
  98. err = writeRule(bWriter, rule, generateUnstable)
  99. if err != nil {
  100. return err
  101. }
  102. }
  103. err = bWriter.Flush()
  104. if err != nil {
  105. return err
  106. }
  107. return compressWriter.Close()
  108. }
  109. func readRule(reader varbin.Reader, recover bool) (rule option.HeadlessRule, err error) {
  110. var ruleType uint8
  111. err = binary.Read(reader, binary.BigEndian, &ruleType)
  112. if err != nil {
  113. return
  114. }
  115. switch ruleType {
  116. case 0:
  117. rule.Type = C.RuleTypeDefault
  118. rule.DefaultOptions, err = readDefaultRule(reader, recover)
  119. case 1:
  120. rule.Type = C.RuleTypeLogical
  121. rule.LogicalOptions, err = readLogicalRule(reader, recover)
  122. default:
  123. err = E.New("unknown rule type: ", ruleType)
  124. }
  125. return
  126. }
  127. func writeRule(writer varbin.Writer, rule option.HeadlessRule, generateUnstable bool) error {
  128. switch rule.Type {
  129. case C.RuleTypeDefault:
  130. return writeDefaultRule(writer, rule.DefaultOptions, generateUnstable)
  131. case C.RuleTypeLogical:
  132. return writeLogicalRule(writer, rule.LogicalOptions, generateUnstable)
  133. default:
  134. panic("unknown rule type: " + rule.Type)
  135. }
  136. }
  137. func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHeadlessRule, err error) {
  138. var lastItemType uint8
  139. for {
  140. var itemType uint8
  141. err = binary.Read(reader, binary.BigEndian, &itemType)
  142. if err != nil {
  143. return
  144. }
  145. switch itemType {
  146. case ruleItemQueryType:
  147. var rawQueryType []uint16
  148. rawQueryType, err = readRuleItemUint16(reader)
  149. if err != nil {
  150. return
  151. }
  152. rule.QueryType = common.Map(rawQueryType, func(it uint16) option.DNSQueryType {
  153. return option.DNSQueryType(it)
  154. })
  155. case ruleItemNetwork:
  156. rule.Network, err = readRuleItemString(reader)
  157. case ruleItemDomain:
  158. var matcher *domain.Matcher
  159. matcher, err = domain.ReadMatcher(reader)
  160. if err != nil {
  161. return
  162. }
  163. rule.DomainMatcher = matcher
  164. if recover {
  165. rule.Domain, rule.DomainSuffix = matcher.Dump()
  166. }
  167. case ruleItemDomainKeyword:
  168. rule.DomainKeyword, err = readRuleItemString(reader)
  169. case ruleItemDomainRegex:
  170. rule.DomainRegex, err = readRuleItemString(reader)
  171. case ruleItemSourceIPCIDR:
  172. rule.SourceIPSet, err = readIPSet(reader)
  173. if err != nil {
  174. return
  175. }
  176. if recover {
  177. rule.SourceIPCIDR = common.Map(rule.SourceIPSet.Prefixes(), netip.Prefix.String)
  178. }
  179. case ruleItemIPCIDR:
  180. rule.IPSet, err = readIPSet(reader)
  181. if err != nil {
  182. return
  183. }
  184. if recover {
  185. rule.IPCIDR = common.Map(rule.IPSet.Prefixes(), netip.Prefix.String)
  186. }
  187. case ruleItemSourcePort:
  188. rule.SourcePort, err = readRuleItemUint16(reader)
  189. case ruleItemSourcePortRange:
  190. rule.SourcePortRange, err = readRuleItemString(reader)
  191. case ruleItemPort:
  192. rule.Port, err = readRuleItemUint16(reader)
  193. case ruleItemPortRange:
  194. rule.PortRange, err = readRuleItemString(reader)
  195. case ruleItemProcessName:
  196. rule.ProcessName, err = readRuleItemString(reader)
  197. case ruleItemProcessPath:
  198. rule.ProcessPath, err = readRuleItemString(reader)
  199. case ruleItemPackageName:
  200. rule.PackageName, err = readRuleItemString(reader)
  201. case ruleItemWIFISSID:
  202. rule.WIFISSID, err = readRuleItemString(reader)
  203. case ruleItemWIFIBSSID:
  204. rule.WIFIBSSID, err = readRuleItemString(reader)
  205. case ruleItemFinal:
  206. err = binary.Read(reader, binary.BigEndian, &rule.Invert)
  207. return
  208. default:
  209. err = E.New("unknown rule item type: ", itemType, ", last type: ", lastItemType)
  210. }
  211. if err != nil {
  212. return
  213. }
  214. lastItemType = itemType
  215. }
  216. }
  217. func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, generateUnstable bool) error {
  218. err := binary.Write(writer, binary.BigEndian, uint8(0))
  219. if err != nil {
  220. return err
  221. }
  222. if len(rule.QueryType) > 0 {
  223. err = writeRuleItemUint16(writer, ruleItemQueryType, common.Map(rule.QueryType, func(it option.DNSQueryType) uint16 {
  224. return uint16(it)
  225. }))
  226. if err != nil {
  227. return err
  228. }
  229. }
  230. if len(rule.Network) > 0 {
  231. err = writeRuleItemString(writer, ruleItemNetwork, rule.Network)
  232. if err != nil {
  233. return err
  234. }
  235. }
  236. if len(rule.Domain) > 0 || len(rule.DomainSuffix) > 0 {
  237. err = binary.Write(writer, binary.BigEndian, ruleItemDomain)
  238. if err != nil {
  239. return err
  240. }
  241. err = domain.NewMatcher(rule.Domain, rule.DomainSuffix, !generateUnstable).Write(writer)
  242. if err != nil {
  243. return err
  244. }
  245. }
  246. if len(rule.DomainKeyword) > 0 {
  247. err = writeRuleItemString(writer, ruleItemDomainKeyword, rule.DomainKeyword)
  248. if err != nil {
  249. return err
  250. }
  251. }
  252. if len(rule.DomainRegex) > 0 {
  253. err = writeRuleItemString(writer, ruleItemDomainRegex, rule.DomainRegex)
  254. if err != nil {
  255. return err
  256. }
  257. }
  258. if len(rule.SourceIPCIDR) > 0 {
  259. err = writeRuleItemCIDR(writer, ruleItemSourceIPCIDR, rule.SourceIPCIDR)
  260. if err != nil {
  261. return E.Cause(err, "source_ip_cidr")
  262. }
  263. }
  264. if len(rule.IPCIDR) > 0 {
  265. err = writeRuleItemCIDR(writer, ruleItemIPCIDR, rule.IPCIDR)
  266. if err != nil {
  267. return E.Cause(err, "ipcidr")
  268. }
  269. }
  270. if len(rule.SourcePort) > 0 {
  271. err = writeRuleItemUint16(writer, ruleItemSourcePort, rule.SourcePort)
  272. if err != nil {
  273. return err
  274. }
  275. }
  276. if len(rule.SourcePortRange) > 0 {
  277. err = writeRuleItemString(writer, ruleItemSourcePortRange, rule.SourcePortRange)
  278. if err != nil {
  279. return err
  280. }
  281. }
  282. if len(rule.Port) > 0 {
  283. err = writeRuleItemUint16(writer, ruleItemPort, rule.Port)
  284. if err != nil {
  285. return err
  286. }
  287. }
  288. if len(rule.PortRange) > 0 {
  289. err = writeRuleItemString(writer, ruleItemPortRange, rule.PortRange)
  290. if err != nil {
  291. return err
  292. }
  293. }
  294. if len(rule.ProcessName) > 0 {
  295. err = writeRuleItemString(writer, ruleItemProcessName, rule.ProcessName)
  296. if err != nil {
  297. return err
  298. }
  299. }
  300. if len(rule.ProcessPath) > 0 {
  301. err = writeRuleItemString(writer, ruleItemProcessPath, rule.ProcessPath)
  302. if err != nil {
  303. return err
  304. }
  305. }
  306. if len(rule.PackageName) > 0 {
  307. err = writeRuleItemString(writer, ruleItemPackageName, rule.PackageName)
  308. if err != nil {
  309. return err
  310. }
  311. }
  312. if len(rule.WIFISSID) > 0 {
  313. err = writeRuleItemString(writer, ruleItemWIFISSID, rule.WIFISSID)
  314. if err != nil {
  315. return err
  316. }
  317. }
  318. if len(rule.WIFIBSSID) > 0 {
  319. err = writeRuleItemString(writer, ruleItemWIFIBSSID, rule.WIFIBSSID)
  320. if err != nil {
  321. return err
  322. }
  323. }
  324. err = binary.Write(writer, binary.BigEndian, ruleItemFinal)
  325. if err != nil {
  326. return err
  327. }
  328. err = binary.Write(writer, binary.BigEndian, rule.Invert)
  329. if err != nil {
  330. return err
  331. }
  332. return nil
  333. }
  334. func readRuleItemString(reader varbin.Reader) ([]string, error) {
  335. return varbin.ReadValue[[]string](reader, binary.BigEndian)
  336. }
  337. func writeRuleItemString(writer varbin.Writer, itemType uint8, value []string) error {
  338. err := writer.WriteByte(itemType)
  339. if err != nil {
  340. return err
  341. }
  342. return varbin.Write(writer, binary.BigEndian, value)
  343. }
  344. func readRuleItemUint16(reader varbin.Reader) ([]uint16, error) {
  345. return varbin.ReadValue[[]uint16](reader, binary.BigEndian)
  346. }
  347. func writeRuleItemUint16(writer varbin.Writer, itemType uint8, value []uint16) error {
  348. err := writer.WriteByte(itemType)
  349. if err != nil {
  350. return err
  351. }
  352. return varbin.Write(writer, binary.BigEndian, value)
  353. }
  354. func writeRuleItemCIDR(writer varbin.Writer, itemType uint8, value []string) error {
  355. var builder netipx.IPSetBuilder
  356. for i, prefixString := range value {
  357. prefix, err := netip.ParsePrefix(prefixString)
  358. if err == nil {
  359. builder.AddPrefix(prefix)
  360. continue
  361. }
  362. addr, addrErr := netip.ParseAddr(prefixString)
  363. if addrErr == nil {
  364. builder.Add(addr)
  365. continue
  366. }
  367. return E.Cause(err, "parse [", i, "]")
  368. }
  369. ipSet, err := builder.IPSet()
  370. if err != nil {
  371. return err
  372. }
  373. err = binary.Write(writer, binary.BigEndian, itemType)
  374. if err != nil {
  375. return err
  376. }
  377. return writeIPSet(writer, ipSet)
  378. }
  379. func readLogicalRule(reader varbin.Reader, recovery bool) (logicalRule option.LogicalHeadlessRule, err error) {
  380. mode, err := reader.ReadByte()
  381. if err != nil {
  382. return
  383. }
  384. switch mode {
  385. case 0:
  386. logicalRule.Mode = C.LogicalTypeAnd
  387. case 1:
  388. logicalRule.Mode = C.LogicalTypeOr
  389. default:
  390. err = E.New("unknown logical mode: ", mode)
  391. return
  392. }
  393. length, err := binary.ReadUvarint(reader)
  394. if err != nil {
  395. return
  396. }
  397. logicalRule.Rules = make([]option.HeadlessRule, length)
  398. for i := uint64(0); i < length; i++ {
  399. logicalRule.Rules[i], err = readRule(reader, recovery)
  400. if err != nil {
  401. err = E.Cause(err, "read logical rule [", i, "]")
  402. return
  403. }
  404. }
  405. err = binary.Read(reader, binary.BigEndian, &logicalRule.Invert)
  406. if err != nil {
  407. return
  408. }
  409. return
  410. }
  411. func writeLogicalRule(writer varbin.Writer, logicalRule option.LogicalHeadlessRule, generateUnstable bool) error {
  412. err := binary.Write(writer, binary.BigEndian, uint8(1))
  413. if err != nil {
  414. return err
  415. }
  416. switch logicalRule.Mode {
  417. case C.LogicalTypeAnd:
  418. err = binary.Write(writer, binary.BigEndian, uint8(0))
  419. case C.LogicalTypeOr:
  420. err = binary.Write(writer, binary.BigEndian, uint8(1))
  421. default:
  422. panic("unknown logical mode: " + logicalRule.Mode)
  423. }
  424. if err != nil {
  425. return err
  426. }
  427. _, err = varbin.WriteUvarint(writer, uint64(len(logicalRule.Rules)))
  428. if err != nil {
  429. return err
  430. }
  431. for _, rule := range logicalRule.Rules {
  432. err = writeRule(writer, rule, generateUnstable)
  433. if err != nil {
  434. return err
  435. }
  436. }
  437. err = binary.Write(writer, binary.BigEndian, logicalRule.Invert)
  438. if err != nil {
  439. return err
  440. }
  441. return nil
  442. }