binary.go 12 KB

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