fake_iptables.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package hostport
  14. import (
  15. "bytes"
  16. "fmt"
  17. "net"
  18. "strings"
  19. "k8s.io/apimachinery/pkg/util/sets"
  20. utiliptables "k8s.io/kubernetes/pkg/util/iptables"
  21. )
  22. type fakeChain struct {
  23. name utiliptables.Chain
  24. rules []string
  25. }
  26. type fakeTable struct {
  27. name utiliptables.Table
  28. chains map[string]*fakeChain
  29. }
  30. type fakeIPTables struct {
  31. tables map[string]*fakeTable
  32. builtinChains map[string]sets.String
  33. }
  34. func NewFakeIPTables() *fakeIPTables {
  35. return &fakeIPTables{
  36. tables: make(map[string]*fakeTable, 0),
  37. builtinChains: map[string]sets.String{
  38. string(utiliptables.TableFilter): sets.NewString("INPUT", "FORWARD", "OUTPUT"),
  39. string(utiliptables.TableNAT): sets.NewString("PREROUTING", "INPUT", "OUTPUT", "POSTROUTING"),
  40. string(utiliptables.TableMangle): sets.NewString("PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING"),
  41. },
  42. }
  43. }
  44. func (f *fakeIPTables) GetVersion() (string, error) {
  45. return "1.4.21", nil
  46. }
  47. func (f *fakeIPTables) getTable(tableName utiliptables.Table) (*fakeTable, error) {
  48. table, ok := f.tables[string(tableName)]
  49. if !ok {
  50. return nil, fmt.Errorf("Table %s does not exist", tableName)
  51. }
  52. return table, nil
  53. }
  54. func (f *fakeIPTables) getChain(tableName utiliptables.Table, chainName utiliptables.Chain) (*fakeTable, *fakeChain, error) {
  55. table, err := f.getTable(tableName)
  56. if err != nil {
  57. return nil, nil, err
  58. }
  59. chain, ok := table.chains[string(chainName)]
  60. if !ok {
  61. return table, nil, fmt.Errorf("Chain %s/%s does not exist", tableName, chainName)
  62. }
  63. return table, chain, nil
  64. }
  65. func (f *fakeIPTables) ensureChain(tableName utiliptables.Table, chainName utiliptables.Chain) (bool, *fakeChain) {
  66. table, chain, err := f.getChain(tableName, chainName)
  67. if err != nil {
  68. // either table or table+chain don't exist yet
  69. if table == nil {
  70. table = &fakeTable{
  71. name: tableName,
  72. chains: make(map[string]*fakeChain),
  73. }
  74. f.tables[string(tableName)] = table
  75. }
  76. chain := &fakeChain{
  77. name: chainName,
  78. rules: make([]string, 0),
  79. }
  80. table.chains[string(chainName)] = chain
  81. return false, chain
  82. }
  83. return true, chain
  84. }
  85. func (f *fakeIPTables) EnsureChain(tableName utiliptables.Table, chainName utiliptables.Chain) (bool, error) {
  86. existed, _ := f.ensureChain(tableName, chainName)
  87. return existed, nil
  88. }
  89. func (f *fakeIPTables) FlushChain(tableName utiliptables.Table, chainName utiliptables.Chain) error {
  90. _, chain, err := f.getChain(tableName, chainName)
  91. if err != nil {
  92. return err
  93. }
  94. chain.rules = make([]string, 0)
  95. return nil
  96. }
  97. func (f *fakeIPTables) DeleteChain(tableName utiliptables.Table, chainName utiliptables.Chain) error {
  98. table, _, err := f.getChain(tableName, chainName)
  99. if err != nil {
  100. return err
  101. }
  102. delete(table.chains, string(chainName))
  103. return nil
  104. }
  105. // Returns index of rule in array; < 0 if rule is not found
  106. func findRule(chain *fakeChain, rule string) int {
  107. for i, candidate := range chain.rules {
  108. if rule == candidate {
  109. return i
  110. }
  111. }
  112. return -1
  113. }
  114. func (f *fakeIPTables) ensureRule(position utiliptables.RulePosition, tableName utiliptables.Table, chainName utiliptables.Chain, rule string) (bool, error) {
  115. _, chain, err := f.getChain(tableName, chainName)
  116. if err != nil {
  117. _, chain = f.ensureChain(tableName, chainName)
  118. }
  119. rule, err = normalizeRule(rule)
  120. if err != nil {
  121. return false, err
  122. }
  123. ruleIdx := findRule(chain, rule)
  124. if ruleIdx >= 0 {
  125. return true, nil
  126. }
  127. if position == utiliptables.Prepend {
  128. chain.rules = append([]string{rule}, chain.rules...)
  129. } else if position == utiliptables.Append {
  130. chain.rules = append(chain.rules, rule)
  131. } else {
  132. return false, fmt.Errorf("Unknown position argument %q", position)
  133. }
  134. return false, nil
  135. }
  136. func normalizeRule(rule string) (string, error) {
  137. normalized := ""
  138. remaining := strings.TrimSpace(rule)
  139. for {
  140. var end int
  141. if strings.HasPrefix(remaining, "--to-destination=") {
  142. remaining = strings.Replace(remaining, "=", " ", 1)
  143. }
  144. if remaining[0] == '"' {
  145. end = strings.Index(remaining[1:], "\"")
  146. if end < 0 {
  147. return "", fmt.Errorf("Invalid rule syntax: mismatched quotes")
  148. }
  149. end += 2
  150. } else {
  151. end = strings.Index(remaining, " ")
  152. if end < 0 {
  153. end = len(remaining)
  154. }
  155. }
  156. arg := remaining[:end]
  157. // Normalize un-prefixed IP addresses like iptables does
  158. if net.ParseIP(arg) != nil {
  159. arg = arg + "/32"
  160. }
  161. if len(normalized) > 0 {
  162. normalized += " "
  163. }
  164. normalized += strings.TrimSpace(arg)
  165. if len(remaining) == end {
  166. break
  167. }
  168. remaining = remaining[end+1:]
  169. }
  170. return normalized, nil
  171. }
  172. func (f *fakeIPTables) EnsureRule(position utiliptables.RulePosition, tableName utiliptables.Table, chainName utiliptables.Chain, args ...string) (bool, error) {
  173. ruleArgs := make([]string, 0)
  174. for _, arg := range args {
  175. // quote args with internal spaces (like comments)
  176. if strings.Index(arg, " ") >= 0 {
  177. arg = fmt.Sprintf("\"%s\"", arg)
  178. }
  179. ruleArgs = append(ruleArgs, arg)
  180. }
  181. return f.ensureRule(position, tableName, chainName, strings.Join(ruleArgs, " "))
  182. }
  183. func (f *fakeIPTables) DeleteRule(tableName utiliptables.Table, chainName utiliptables.Chain, args ...string) error {
  184. _, chain, err := f.getChain(tableName, chainName)
  185. if err == nil {
  186. rule := strings.Join(args, " ")
  187. ruleIdx := findRule(chain, rule)
  188. if ruleIdx < 0 {
  189. return nil
  190. }
  191. chain.rules = append(chain.rules[:ruleIdx], chain.rules[ruleIdx+1:]...)
  192. }
  193. return nil
  194. }
  195. func (f *fakeIPTables) IsIpv6() bool {
  196. return false
  197. }
  198. func saveChain(chain *fakeChain, data *bytes.Buffer) {
  199. for _, rule := range chain.rules {
  200. data.WriteString(fmt.Sprintf("-A %s %s\n", chain.name, rule))
  201. }
  202. }
  203. func (f *fakeIPTables) SaveInto(tableName utiliptables.Table, buffer *bytes.Buffer) error {
  204. table, err := f.getTable(tableName)
  205. if err != nil {
  206. return err
  207. }
  208. buffer.WriteString(fmt.Sprintf("*%s\n", table.name))
  209. rules := bytes.NewBuffer(nil)
  210. for _, chain := range table.chains {
  211. buffer.WriteString(fmt.Sprintf(":%s - [0:0]\n", string(chain.name)))
  212. saveChain(chain, rules)
  213. }
  214. buffer.Write(rules.Bytes())
  215. buffer.WriteString("COMMIT\n")
  216. return nil
  217. }
  218. func (f *fakeIPTables) restore(restoreTableName utiliptables.Table, data []byte, flush utiliptables.FlushFlag) error {
  219. allLines := string(data)
  220. buf := bytes.NewBuffer(data)
  221. var tableName utiliptables.Table
  222. for {
  223. line, err := buf.ReadString('\n')
  224. if err != nil {
  225. break
  226. }
  227. if line[0] == '#' {
  228. continue
  229. }
  230. line = strings.TrimSuffix(line, "\n")
  231. if strings.HasPrefix(line, "*") {
  232. tableName = utiliptables.Table(line[1:])
  233. }
  234. if tableName != "" {
  235. if restoreTableName != "" && restoreTableName != tableName {
  236. continue
  237. }
  238. if strings.HasPrefix(line, ":") {
  239. chainName := utiliptables.Chain(strings.Split(line[1:], " ")[0])
  240. if flush == utiliptables.FlushTables {
  241. table, chain, _ := f.getChain(tableName, chainName)
  242. if chain != nil {
  243. delete(table.chains, string(chainName))
  244. }
  245. }
  246. _, _ = f.ensureChain(tableName, chainName)
  247. // The --noflush option for iptables-restore doesn't work for user-defined chains, only builtin chains.
  248. // We should flush user-defined chains if the chain is not to be deleted
  249. if !f.isBuiltinChain(tableName, chainName) && !strings.Contains(allLines, "-X "+string(chainName)) {
  250. if err := f.FlushChain(tableName, chainName); err != nil {
  251. return err
  252. }
  253. }
  254. } else if strings.HasPrefix(line, "-A") {
  255. parts := strings.Split(line, " ")
  256. if len(parts) < 3 {
  257. return fmt.Errorf("Invalid iptables rule '%s'", line)
  258. }
  259. chainName := utiliptables.Chain(parts[1])
  260. rule := strings.TrimPrefix(line, fmt.Sprintf("-A %s ", chainName))
  261. _, err := f.ensureRule(utiliptables.Append, tableName, chainName, rule)
  262. if err != nil {
  263. return err
  264. }
  265. } else if strings.HasPrefix(line, "-I") {
  266. parts := strings.Split(line, " ")
  267. if len(parts) < 3 {
  268. return fmt.Errorf("Invalid iptables rule '%s'", line)
  269. }
  270. chainName := utiliptables.Chain(parts[1])
  271. rule := strings.TrimPrefix(line, fmt.Sprintf("-I %s ", chainName))
  272. _, err := f.ensureRule(utiliptables.Prepend, tableName, chainName, rule)
  273. if err != nil {
  274. return err
  275. }
  276. } else if strings.HasPrefix(line, "-X") {
  277. parts := strings.Split(line, " ")
  278. if len(parts) < 2 {
  279. return fmt.Errorf("Invalid iptables rule '%s'", line)
  280. }
  281. if err := f.DeleteChain(tableName, utiliptables.Chain(parts[1])); err != nil {
  282. return err
  283. }
  284. } else if line == "COMMIT" {
  285. if restoreTableName == tableName {
  286. return nil
  287. }
  288. tableName = ""
  289. }
  290. }
  291. }
  292. return nil
  293. }
  294. func (f *fakeIPTables) Restore(tableName utiliptables.Table, data []byte, flush utiliptables.FlushFlag, counters utiliptables.RestoreCountersFlag) error {
  295. return f.restore(tableName, data, flush)
  296. }
  297. func (f *fakeIPTables) RestoreAll(data []byte, flush utiliptables.FlushFlag, counters utiliptables.RestoreCountersFlag) error {
  298. return f.restore("", data, flush)
  299. }
  300. func (f *fakeIPTables) AddReloadFunc(reloadFunc func()) {
  301. }
  302. func (f *fakeIPTables) Destroy() {
  303. }
  304. func (f *fakeIPTables) isBuiltinChain(tableName utiliptables.Table, chainName utiliptables.Chain) bool {
  305. if builtinChains, ok := f.builtinChains[string(tableName)]; ok && builtinChains.Has(string(chainName)) {
  306. return true
  307. }
  308. return false
  309. }