| 55 | } |
| 56 | |
| 57 | func (validator *Validator) Run() error { |
| 58 | log.Infof("Starting iptables validation. This check verifies that iptables rules are properly established for the network.") |
| 59 | s := Service{ |
| 60 | validator.Config, |
| 61 | } |
| 62 | sError := make(chan error, 1) |
| 63 | sTimer := time.NewTimer(s.Config.ProbeTimeout) |
| 64 | defer sTimer.Stop() |
| 65 | go func() { |
| 66 | sError <- s.Run() |
| 67 | }() |
| 68 | |
| 69 | // infinite loop |
| 70 | go func() { |
| 71 | c := Client{Config: validator.Config} |
| 72 | <-c.Config.ServerReadyBarrier |
| 73 | for { |
| 74 | _ = c.Run() |
| 75 | // Avoid spamming the request to the validation server. |
| 76 | // Since the TIMEWAIT socket is cleaned up in 60 second, |
| 77 | // it's maintaining 60 TIMEWAIT sockets. Not big deal. |
| 78 | time.Sleep(time.Second) |
| 79 | } |
| 80 | }() |
| 81 | select { |
| 82 | case <-sTimer.C: |
| 83 | return fmt.Errorf("validation timeout") |
| 84 | case err := <-sError: |
| 85 | if err == nil { |
| 86 | log.Info("Validation passed, iptables rules established") |
| 87 | } else { |
| 88 | log.Errorf("Validation failed: %v", err) |
| 89 | } |
| 90 | return err |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | // TODO(lambdai): remove this if iptables only need to redirect to outbound proxy port on A call A |
| 95 | func genListenerAddress(ip netip.Addr, ports []string) []string { |