@@ -2,15 +2,16 @@ package main
22
33import (
44 "github.com/dominikh/simple-router/conntrack"
5+ "github.com/dominikh/simple-router/lookup"
6+ "github.com/dominikh/simple-router/nat"
57
68 "flag"
79 "fmt"
8- "net"
910 "os"
1011 "text/tabwriter"
1112)
1213
13- // -n: don't resolve host/portnames
14+ // TODO implement the following flags
1415// -p <protocol> : display connections by protocol
1516// -s <source-host> : display connections by source
1617// -d <destination-host>: display connections by destination
@@ -26,65 +27,25 @@ var onlyRouted = flag.Bool("R", false, "Display only connections routed through
2627var noResolve = flag .Bool ("n" , false , "Do not resolve hostnames" ) // TODO resolve port names as well
2728var noHeader = flag .Bool ("o" , false , "Strip output header" )
2829
29- var (
30- displaySNAT bool = true
31- displayDNAT bool = true
32- displayLocal bool = false
33- displayRouted bool = false
34- )
35-
36- var localIPs = make ([]* net.IPNet , 0 )
37-
38- func isLocalIP (ip net.IP ) bool {
39- for _ , localIP := range localIPs {
40- if localIP .IP .Equal (ip ) {
41- return true
42- }
43- }
44-
45- return false
46- }
47-
48- func init () {
49- addresses , err := net .InterfaceAddrs ()
50- if err != nil {
51- panic (err )
52- }
53-
54- for _ , address := range addresses {
55- localIPs = append (localIPs , address .(* net.IPNet ))
56- }
57- }
58-
5930func main () {
6031 flag .Parse ()
6132
33+ var which nat.Flag
34+
6235 if * onlySNAT {
63- displaySNAT = true
64- displayDNAT = false
65- displayLocal = false
66- displayRouted = false
36+ which = nat .SNAT
6737 }
6838
6939 if * onlyDNAT {
70- displaySNAT = false
71- displayDNAT = true
72- displayLocal = false
73- displayRouted = false
40+ which = nat .DNAT
7441 }
7542
7643 if * onlyLocal {
77- displaySNAT = false
78- displayDNAT = false
79- displayLocal = true
80- displayRouted = false
44+ which = nat .Local
8145 }
8246
8347 if * onlyRouted {
84- displaySNAT = false
85- displayDNAT = false
86- displayLocal = false
87- displayRouted = true
48+ which = nat .Routed
8849 }
8950
9051 flows , err := conntrack .Flows ()
@@ -99,88 +60,19 @@ func main() {
9960 fmt .Fprintln (tabWriter , "Proto\t Source Address\t Destination Address\t State" )
10061 }
10162
102- for _ , flow := range flows {
103- if (displaySNAT && isSNAT (flow )) ||
104- (displayDNAT && isDNAT (flow )) ||
105- (displayLocal && isLocal (flow )) ||
106- (displayRouted && isRouted (flow )) {
107-
108- sHostname := resolve (flow .Original .Source )
109- dHostname := resolve (flow .Original .Destination )
63+ natFlows := nat .GetNAT (flows , which )
64+ for _ , flow := range natFlows {
65+ sHostname := lookup .Resolve (flow .Original .Source , * noResolve )
66+ dHostname := lookup .Resolve (flow .Original .Destination , * noResolve )
11067
111- fmt .Fprintf (tabWriter , "%s\t %s:%d\t %s:%d\t %s\n " ,
112- flow .Protocol ,
113- sHostname ,
114- flow .Original .SPort ,
115- dHostname ,
116- flow .Original .DPort ,
117- flow .State ,
118- )
119- }
68+ fmt .Fprintf (tabWriter , "%s\t %s:%d\t %s:%d\t %s\n " ,
69+ flow .Protocol ,
70+ sHostname ,
71+ flow .Original .SPort ,
72+ dHostname ,
73+ flow .Original .DPort ,
74+ flow .State ,
75+ )
12076 }
12177 tabWriter .Flush ()
12278}
123-
124- func resolve (ip net.IP ) string {
125- if * noResolve {
126- return ip .String ()
127- }
128-
129- lookup , err := net .LookupAddr (ip .String ())
130- if err == nil && len (lookup ) > 0 {
131- return lookup [0 ]
132- }
133-
134- return ip .String ()
135- }
136-
137- func isSNAT (flow conntrack.Flow ) bool {
138- // SNATed flows should reply to our WAN IP, not a LAN IP.
139- if flow .Original .Source .Equal (flow .Reply .Destination ) {
140- return false
141- }
142-
143- if ! flow .Original .Destination .Equal (flow .Reply .Source ) {
144- return false
145- }
146-
147- return true
148- }
149-
150- func isDNAT (flow conntrack.Flow ) bool {
151- // Reply must go back to the source; Reply mustn't come from the WAN IP
152- if flow .Original .Source .Equal (flow .Reply .Destination ) && ! flow .Original .Destination .Equal (flow .Reply .Source ) {
153- return true
154- }
155-
156- // Taken straight from original netstat-nat, labelled "DNAT (1 interface)"
157- if ! flow .Original .Source .Equal (flow .Reply .Source ) && ! flow .Original .Source .Equal (flow .Reply .Destination ) && ! flow .Original .Destination .Equal (flow .Reply .Source ) && flow .Original .Destination .Equal (flow .Reply .Destination ) {
158- return true
159- }
160-
161- return false
162- }
163-
164- func isLocal (flow conntrack.Flow ) bool {
165- // no NAT
166- if flow .Original .Source .Equal (flow .Reply .Destination ) && flow .Original .Destination .Equal (flow .Reply .Source ) {
167- // At least one local address
168- if isLocalIP (flow .Original .Source ) || isLocalIP (flow .Original .Destination ) || isLocalIP (flow .Reply .Source ) || isLocalIP (flow .Reply .Destination ) {
169- return true
170- }
171- }
172-
173- return false
174- }
175-
176- func isRouted (flow conntrack.Flow ) bool {
177- // no NAT
178- if flow .Original .Source .Equal (flow .Reply .Destination ) && flow .Original .Destination .Equal (flow .Reply .Source ) {
179- // No local addresses
180- if ! isLocalIP (flow .Original .Source ) && ! isLocalIP (flow .Original .Destination ) && ! isLocalIP (flow .Reply .Source ) && ! isLocalIP (flow .Reply .Destination ) {
181- return true
182- }
183- }
184-
185- return false
186- }
0 commit comments