Skip to content

Commit

Permalink
Add restricted session
Browse files Browse the repository at this point in the history
Adds the ability to block network traffic on SSH sessions.
The deny/allow lists of IPs are specified in teleport.yaml file.
Supports both IPv4 and IPv6 communication.

This feature currently relies on enhanced recording for
cgroup management so that needs to be enabled as well.

-- Design rationale:
This patch uses Linux Security Module (LSM) hooks, specifically
security_socket_connect and security_socket_sendmsg, to control
egress traffic. The LSM provides two advantages over socket filtering
program types.
- It's executed early enough that the task information is available.
  This makes it easy to report PID, COMM, etc.
- It becomes a model for extending restrictions beyond networking.

The set of enforced cgroups is stored in a BPF hash map and the
deny/allow lists are stored in BPF trie maps. An IP address is
first checked against the allow list. If found, it's checked for
an override in the deny list. The policy is default deny. However,
the absence of the NetworkRestrictions API object is allow all.

IPv4 addresses are additionally registered in IPv6 trie (as mapped)
to account for dual stacks. However it is unclear if this is sufficient
as 4-to-6 transition methods utilize a multitude of translation and
tunneling methods.
  • Loading branch information
eyakubovich committed Jul 16, 2021
1 parent a0f9729 commit 154833d
Show file tree
Hide file tree
Showing 66 changed files with 6,124 additions and 2,015 deletions.
32 changes: 24 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ CLANG_FORMAT ?= $(shell which clang-format || which clang-format-10)
LLVM_STRIP ?= $(shell which llvm-strip || which llvm-strip-10)
KERNEL_ARCH := $(shell uname -m | sed 's/x86_64/x86/')
INCLUDES :=
BPF_BUILDDIR := lib/bpf/bytecode
ER_BPF_BUILDDIR := lib/bpf/bytecode
RS_BPF_BUILDDIR := lib/restrictedsession/bytecode

# Get Clang's default includes on this system. We'll explicitly add these dirs
# to the includes list when compiling with `-target bpf` because otherwise some
Expand Down Expand Up @@ -160,16 +161,30 @@ $(BUILDDIR)/tsh:
# Requires a recent version of clang and libbpf installed.
#
ifeq ("$(with_bpf)","yes")
$(BPF_BUILDDIR):
mkdir -p $(BPF_BUILDDIR)
$(ER_BPF_BUILDDIR):
mkdir -p $(ER_BPF_BUILDDIR)

$(RS_BPF_BUILDDIR):
mkdir -p $(RS_BPF_BUILDDIR)

# Build BPF code
$(BPF_BUILDDIR)/%.bpf.o: bpf/%.bpf.c $(wildcard bpf/*.h) | $(BPF_BUILDDIR)
$(ER_BPF_BUILDDIR)/%.bpf.o: bpf/enhancedrecording/%.bpf.c $(wildcard bpf/*.h) | $(ER_BPF_BUILDDIR)
$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(KERNEL_ARCH) $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) -c $(filter %.c,$^) -o $@
$(LLVM_STRIP) -g $@ # strip useless DWARF info

# Build BPF code
$(RS_BPF_BUILDDIR)/%.bpf.o: bpf/restrictedsession/%.bpf.c $(wildcard bpf/*.h) | $(RS_BPF_BUILDDIR)
$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(KERNEL_ARCH) $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) -c $(filter %.c,$^) -o $@
$(LLVM_STRIP) -g $@ # strip useless DWARF info

.PHONY: bpf-rs-bytecode
bpf-rs-bytecode: $(RS_BPF_BUILDDIR)/restricted.bpf.o

.PHONY: bpf-er-bytecode
bpf-er-bytecode: $(ER_BPF_BUILDDIR)/command.bpf.o $(ER_BPF_BUILDDIR)/disk.bpf.o $(ER_BPF_BUILDDIR)/network.bpf.o $(ER_BPF_BUILDDIR)/counter_test.bpf.o

.PHONY: bpf-bytecode
bpf-bytecode: $(BPF_BUILDDIR)/command.bpf.o $(BPF_BUILDDIR)/disk.bpf.o $(BPF_BUILDDIR)/network.bpf.o $(BPF_BUILDDIR)/counter_test.bpf.o
bpf-bytecode: bpf-er-bytecode bpf-rs-bytecode

# Generate vmlinux.h based on the installed kernel
.PHONY: update-vmlinux-h
Expand Down Expand Up @@ -210,7 +225,8 @@ endif
clean:
@echo "---> Cleaning up OSS build artifacts."
rm -rf $(BUILDDIR)
rm -rf $(BPF_BUILDDIR)
rm -rf $(ER_BPF_BUILDDIR)
rm -rf $(RS_BPF_BUILDDIR)
-go clean -cache
rm -rf $(GOPKGDIR)
rm -rf teleport
Expand Down Expand Up @@ -335,7 +351,7 @@ test-go: PACKAGES := $(shell go list ./... | grep -v integration)
test-go: CHAOS_FOLDERS := $(shell find . -type f -name '*chaos*.go' -not -path '*/vendor/*' | xargs dirname | uniq)
test-go: $(VERSRC)
$(CGOFLAG) go test -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)
$(CGOFLAG) go test -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" -test.run=TestChaos $(CHAOS_FOLDERS) -cover
$(CGOFLAG) go test -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" -test.run=TestChaos $(CHAOS_FOLDERS) -cover $(ADDFLAGS)

#
# Runs all Go tests except integration and chaos, called by CI/CD.
Expand All @@ -344,7 +360,7 @@ UNIT_ROOT_REGEX := ^TestRoot
.PHONY: test-go-root
test-go-root: ensure-webassets bpf-bytecode
test-go-root: FLAGS ?= '-race'
test-go-root: PACKAGES := $(shell go list ./... | grep -v integration)
test-go-root: PACKAGES := $(shell go list $(ADDFLAGS) ./... | grep -v integration)
test-go-root: $(VERSRC)
$(CGOFLAG) go test -run "$(UNIT_ROOT_REGEX)" -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)

Expand Down
31 changes: 31 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1631,3 +1631,34 @@ func (c *Client) DeleteLock(ctx context.Context, name string) error {
func (c *Client) DeleteAllLocks(context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}

// GetNetworkRestrictions retrieves the network restrictions
func (c *Client) GetNetworkRestrictions(ctx context.Context) (types.NetworkRestrictions, error) {
nr, err := c.grpc.GetNetworkRestrictions(ctx, &empty.Empty{}, c.callOpts...)
if err != nil {
return nil, trail.FromGRPC(err)
}
return nr, nil
}

// SetNetworkRestrictions updates the network restrictions
func (c *Client) SetNetworkRestrictions(ctx context.Context, nr types.NetworkRestrictions) error {
restrictionsV4, ok := nr.(*types.NetworkRestrictionsV4)
if !ok {
return trace.BadParameter("invalid type %T", nr)
}
_, err := c.grpc.SetNetworkRestrictions(ctx, restrictionsV4, c.callOpts...)
if err != nil {
return trail.FromGRPC(err)
}
return nil
}

// DeleteNetworkRestrictions deletes the network restrictions
func (c *Client) DeleteNetworkRestrictions(ctx context.Context) error {
_, err := c.grpc.DeleteNetworkRestrictions(ctx, &empty.Empty{}, c.callOpts...)
if err != nil {
return trail.FromGRPC(err)
}
return nil
}
Loading

0 comments on commit 154833d

Please sign in to comment.