cut.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package secrules
  15. import (
  16. "bytes"
  17. "fmt"
  18. "net"
  19. "sort"
  20. "yunion.io/x/pkg/util/netutils"
  21. "yunion.io/x/pkg/util/regutils"
  22. )
  23. type securityRuleCut struct {
  24. r SecurityRule
  25. protocolCut bool
  26. netCut bool
  27. portCut bool
  28. v4ranges []netutils.IPV4AddrRange
  29. v6ranges []netutils.IPV6AddrRange
  30. }
  31. func (src *securityRuleCut) String() string {
  32. s := fmt.Sprintf("[%s;v4=%s;v6=%s;protocolCut=%v;netCut=%v;portCut=%v]",
  33. src.r.String(),
  34. netutils.IPV4AddrRangeList(src.v4ranges).String(),
  35. netutils.IPV6AddrRangeList(src.v6ranges).String(),
  36. src.protocolCut, src.netCut, src.portCut)
  37. return s
  38. }
  39. func (src *securityRuleCut) isCut() bool {
  40. return src.protocolCut && src.netCut && src.portCut
  41. }
  42. func (src securityRuleCut) genRules() []SecurityRule {
  43. src.v4ranges = netutils.IPV4AddrRangeList(src.v4ranges).Merge()
  44. src.v6ranges = netutils.IPV6AddrRangeList(src.v6ranges).Merge()
  45. rs := make([]SecurityRule, 0)
  46. if len(src.v4ranges) == 1 && src.v4ranges[0].IsAll() && len(src.v6ranges) == 1 && src.v6ranges[0].IsAll() {
  47. rule := src.r
  48. rule.IPNet = nil
  49. rs = append(rs, rule)
  50. return rs
  51. }
  52. for i := range src.v4ranges {
  53. nets := src.v4ranges[i].ToIPNets()
  54. for _, net := range nets {
  55. rule := src.r
  56. rule.IPNet = net
  57. rs = append(rs, rule)
  58. }
  59. }
  60. for i := range src.v6ranges {
  61. nets := src.v6ranges[i].ToIPNets()
  62. for _, net := range nets {
  63. rule := src.r
  64. rule.IPNet = net
  65. rs = append(rs, rule)
  66. }
  67. }
  68. return rs
  69. }
  70. func newSecurityRuleSetCuts(r SecurityRule) securityRuleCuts {
  71. var v4ranges []netutils.IPV4AddrRange
  72. var v6ranges []netutils.IPV6AddrRange
  73. if r.IPNet == nil {
  74. // expand
  75. v4ranges = append(v4ranges, netutils.AllIPV4AddrRange)
  76. v6ranges = append(v6ranges, netutils.AllIPV6AddrRange)
  77. } else {
  78. if regutils.MatchCIDR(r.IPNet.String()) {
  79. v4ranges = append(v4ranges, netutils.NewIPV4AddrRangeFromIPNet(r.IPNet))
  80. } else {
  81. v6ranges = append(v6ranges, netutils.NewIPV6AddrRangeFromIPNet(r.IPNet))
  82. }
  83. }
  84. return []securityRuleCut{
  85. {
  86. r: r,
  87. v4ranges: v4ranges,
  88. v6ranges: v6ranges,
  89. },
  90. }
  91. }
  92. type securityRuleCuts []securityRuleCut
  93. func (srcs securityRuleCuts) String() string {
  94. buf := bytes.Buffer{}
  95. for i := range srcs {
  96. s := srcs[i].String()
  97. buf.WriteString(s)
  98. buf.WriteString("\n")
  99. }
  100. return buf.String()
  101. }
  102. func (srcs securityRuleCuts) securityRuleSet() SecurityRuleSet {
  103. srs := SecurityRuleSet{}
  104. for i := range srcs {
  105. src := &srcs[i]
  106. if src.isCut() {
  107. continue
  108. }
  109. srs = append(srs, src.genRules()...)
  110. }
  111. return srs
  112. }
  113. func (srcs securityRuleCuts) cutOutProtocol(protocol string) securityRuleCuts {
  114. r := securityRuleCuts{}
  115. for _, src := range srcs {
  116. sr := src.r
  117. if sr.Protocol == protocol {
  118. // cut
  119. src.protocolCut = true
  120. r = append(r, src)
  121. } else if sr.Protocol == PROTO_ANY {
  122. for _, p := range protocolsSupported {
  123. src_ := src
  124. src_.r.Protocol = p
  125. if p == protocol {
  126. src_.protocolCut = true
  127. }
  128. r = append(r, src_)
  129. }
  130. } else if protocol == PROTO_ANY {
  131. // cut
  132. src.protocolCut = true
  133. r = append(r, src)
  134. } else {
  135. // retain
  136. r = append(r, src)
  137. }
  138. }
  139. return r
  140. }
  141. func isV6(n *net.IPNet) bool {
  142. return regutils.MatchCIDR6(n.String())
  143. }
  144. func (srcs securityRuleCuts) cutOutIPNet(protocol string, n *net.IPNet) securityRuleCuts {
  145. r := securityRuleCuts{}
  146. isWildMatch := isWildNet(n)
  147. isV6 := false
  148. var v4n netutils.IPV4AddrRange
  149. var v6n netutils.IPV6AddrRange
  150. if !isWildMatch {
  151. if regutils.MatchCIDR6(n.String()) {
  152. isV6 = true
  153. v6n = netutils.NewIPV6AddrRangeFromIPNet(n)
  154. } else {
  155. v4n = netutils.NewIPV4AddrRangeFromIPNet(n)
  156. }
  157. }
  158. for i := range srcs {
  159. src := srcs[i]
  160. if src.netCut {
  161. r = append(r, src)
  162. continue
  163. }
  164. if src.r.Protocol != protocol && protocol != PROTO_ANY {
  165. r = append(r, src)
  166. continue
  167. }
  168. if isWildMatch {
  169. src.netCut = true
  170. r = append(r, src)
  171. continue
  172. }
  173. if isV6 {
  174. src.v6ranges = netutils.IPV6AddrRangeList(src.v6ranges).Substract(v6n)
  175. } else {
  176. src.v4ranges = netutils.IPV4AddrRangeList(src.v4ranges).Substract(v4n)
  177. }
  178. r = append(r, src)
  179. }
  180. return r
  181. }
  182. func (srcs securityRuleCuts) cutOutPortRange(protocol string, portStart, portEnd uint16) securityRuleCuts {
  183. pr1 := &portRange{
  184. start: portStart,
  185. end: portEnd,
  186. }
  187. r := securityRuleCuts{}
  188. for _, src := range srcs {
  189. if src.r.Protocol != protocol {
  190. src_ := src
  191. r = append(r, src_)
  192. continue
  193. }
  194. sr := src.r
  195. if len(sr.Ports) > 0 {
  196. ps := newPortsFromInts(sr.Ports...)
  197. left, sub := ps.substractPortRange(pr1)
  198. if len(left) > 0 {
  199. src_ := src
  200. src_.r.Ports = left.IntSlice()
  201. r = append(r, src_)
  202. }
  203. if len(sub) > 0 {
  204. src_ := src
  205. src_.r.Ports = left.IntSlice()
  206. src_.portCut = true
  207. r = append(r, src_)
  208. }
  209. } else if sr.PortStart > 0 && sr.PortEnd > 0 {
  210. pr := newPortRange(uint16(sr.PortStart), uint16(sr.PortEnd))
  211. left, sub := pr.substractPortRange(pr1)
  212. for _, l := range left {
  213. src_ := src
  214. src_.r.PortStart = int(l.start)
  215. src_.r.PortEnd = int(l.end)
  216. r = append(r, src_)
  217. }
  218. if sub != nil && sub.count() > 0 {
  219. src_ := src
  220. src_.r.PortStart = int(sub.start)
  221. src_.r.PortEnd = int(sub.end)
  222. src_.portCut = true
  223. r = append(r, src_)
  224. }
  225. } else {
  226. {
  227. nns := [][2]int32{
  228. [2]int32{1, int32(portStart) - 1},
  229. [2]int32{int32(portEnd) + 1, 65535},
  230. }
  231. for _, nn := range nns {
  232. if nn[0] <= nn[1] {
  233. src_ := src
  234. src_.r.PortStart = int(nn[0])
  235. src_.r.PortEnd = int(nn[1])
  236. r = append(r, src_)
  237. }
  238. }
  239. }
  240. {
  241. src_ := src
  242. src_.r.PortStart = int(portStart)
  243. src_.r.PortEnd = int(portEnd)
  244. src_.portCut = true
  245. r = append(r, src_)
  246. }
  247. }
  248. }
  249. return r
  250. }
  251. func (srcs securityRuleCuts) cutOutPorts(protocol string, ps1 []uint16) securityRuleCuts {
  252. r := securityRuleCuts{}
  253. for _, src := range srcs {
  254. if src.r.Protocol != protocol {
  255. src_ := src
  256. r = append(r, src_)
  257. continue
  258. }
  259. sr := src.r
  260. if len(sr.Ports) > 0 {
  261. ps0 := newPortsFromInts(sr.Ports...)
  262. left, sub := ps0.substractPorts(ps1)
  263. if len(left) > 0 {
  264. src_ := src
  265. src_.r.Ports = left.IntSlice()
  266. r = append(r, src_)
  267. }
  268. if len(sub) > 0 {
  269. src_ := src
  270. src_.r.Ports = sub.IntSlice()
  271. src_.portCut = true
  272. r = append(r, src_)
  273. }
  274. } else if sr.PortStart > 0 && sr.PortEnd > 0 {
  275. pr := newPortRange(uint16(sr.PortStart), uint16(sr.PortEnd))
  276. ps := ports(ps1)
  277. left, sub := pr.substractPorts(ps)
  278. for _, l := range left {
  279. src_ := src
  280. src_.r.PortStart = int(l.start)
  281. src_.r.PortEnd = int(l.end)
  282. r = append(r, src_)
  283. }
  284. if len(sub) > 0 {
  285. src_ := src
  286. src_.r.Ports = sub.IntSlice()
  287. src_.r.PortStart = 0
  288. src_.r.PortEnd = 0
  289. src_.portCut = true
  290. r = append(r, src_)
  291. }
  292. } else {
  293. sort.Slice(ps1, func(i, j int) bool {
  294. return ps1[i] < ps1[j]
  295. })
  296. add := func(s, e uint16) {
  297. src_ := src
  298. src_.r.PortStart = int(s)
  299. src_.r.PortEnd = int(e)
  300. r = append(r, src_)
  301. }
  302. s := uint16(1)
  303. for _, p := range ps1 {
  304. if s <= p-1 {
  305. add(s, p-1)
  306. s = p + 1
  307. }
  308. }
  309. if s != 0 && s <= 65535 {
  310. add(s, 65535)
  311. }
  312. {
  313. src_ := src
  314. src_.r.Ports = ports(ps1).IntSlice()
  315. src_.portCut = true
  316. r = append(r, src_)
  317. }
  318. }
  319. }
  320. return r
  321. }
  322. func (srcs securityRuleCuts) cutOutPortsAll() securityRuleCuts {
  323. r := securityRuleCuts{}
  324. for _, src := range srcs {
  325. src_ := src
  326. src_.portCut = true
  327. r = append(r, src_)
  328. }
  329. return r
  330. }