-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
secure farmer lan #2520
base: main
Are you sure you want to change the base?
secure farmer lan #2520
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
package nft | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"os/exec" | ||
|
||
"github.com/rs/zerolog/log" | ||
"github.com/vishvananda/netlink" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
@@ -32,3 +35,93 @@ func Apply(r io.Reader, ns string) error { | |
} | ||
return nil | ||
} | ||
|
||
// DropTrafficToLAN drops all the outgoing traffic to any peers on | ||
// the same lan network, but allow dicovery port for ygg/myc by accepting | ||
// traffic to/from dest/src ports. | ||
// @th,0,16 and @th,16,16 is raw expression for sport/dport in transport header | ||
// used due to limitation on the installed nft v0.9.1 | ||
func DropTrafficToLAN(namesapce string) error { | ||
dgw, err := getDefaultGW() | ||
if err != nil { | ||
return fmt.Errorf("failed to find default gateway: %w", err) | ||
} | ||
|
||
if !dgw.IP.IsPrivate() { | ||
log.Warn().Msg("skip LAN security. default gateway is public") | ||
return nil | ||
} | ||
|
||
ipAddr := dgw.IP.String() | ||
netAddr := getNetworkRange(dgw) | ||
macAddr := dgw.HardwareAddr.String() | ||
log.Debug(). | ||
Str("ipAddr", ipAddr). | ||
Str("netAddr", netAddr). | ||
Str("macAddr", macAddr). | ||
Msg("drop traffic to lan with the default gateway") | ||
|
||
var buf bytes.Buffer | ||
buf.WriteString("table inet filter {\n") | ||
buf.WriteString(" chain forward {\n") | ||
// allow traffic on sport ygg/myc discovery ports | ||
buf.WriteString(" meta l4proto { tcp, udp } @th,0,16 { 9651, 9650 } accept;\n") | ||
// allow traffic on dport ygg/myc discovery ports | ||
buf.WriteString(" meta l4proto { tcp, udp } @th,16,16 { 9651, 9650 } accept;\n") | ||
// allow traffic to the default gateway | ||
buf.WriteString(fmt.Sprintf(" ip daddr %s accept;\n", ipAddr)) | ||
// allow traffic to any ip not in the network range | ||
buf.WriteString(fmt.Sprintf(" ip daddr != %s accept;\n", netAddr)) | ||
// only drop traffic if it destined to mac addr other than the default gateway | ||
buf.WriteString(fmt.Sprintf(" ether daddr != %s drop;\n", macAddr)) | ||
buf.WriteString(" }\n") | ||
buf.WriteString("}\n") | ||
|
||
// applied on the ndmz namespace | ||
return Apply(&buf, namesapce) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. namesapce ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, where do you apply the new table ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in |
||
} | ||
|
||
func getDefaultGW() (netlink.Neigh, error) { | ||
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) | ||
if err != nil { | ||
return netlink.Neigh{}, fmt.Errorf("failed to list routes: %v", err) | ||
} | ||
|
||
var defaultRoute *netlink.Route | ||
for _, route := range routes { | ||
if route.Dst == nil { | ||
defaultRoute = &route | ||
break | ||
} | ||
} | ||
|
||
if defaultRoute == nil { | ||
return netlink.Neigh{}, fmt.Errorf("default route not found") | ||
} | ||
|
||
if defaultRoute.Gw == nil { | ||
return netlink.Neigh{}, fmt.Errorf("default route has no gateway") | ||
} | ||
|
||
neighs, err := netlink.NeighList(0, netlink.FAMILY_V4) | ||
if err != nil { | ||
return netlink.Neigh{}, fmt.Errorf("failed to list neighbors: %v", err) | ||
} | ||
|
||
for _, neigh := range neighs { | ||
if neigh.IP.Equal(defaultRoute.Gw) { | ||
return neigh, nil | ||
} | ||
} | ||
|
||
return netlink.Neigh{}, errors.New("failed to get default gw") | ||
} | ||
|
||
func getNetworkRange(ip netlink.Neigh) string { | ||
mask := ip.IP.DefaultMask() | ||
network := ip.IP.Mask(mask) | ||
ones, _ := mask.Size() | ||
networkRange := fmt.Sprintf("%s/%d", network.String(), ones) | ||
|
||
return networkRange | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're missing the type here
type filter hook forward priority filter; policy accept;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is already handled in the initial nft setup