Skip to content

Commit

Permalink
remote/ssh: add new ssh backend
Browse files Browse the repository at this point in the history
This backend allows BCC to connect and run eBPF on remote targets
with bpfd's stdin/stdout attached to ssh sockets. It deliberately
avoids the complications of ssh authentication and authorization,
so the ssh communication channel should be setup before BCC runs.

The environment variables necessary to use this backend:
BCC_REMOTE=ssh
BCC_REMOTE_SSH_USER=<user>
BCC_REMOTE_SSH_ADDR=<ip-addr-or-hostname>

Optional variables:
BCC_REMOTE_SSH_CMD=<cmd> (default runs 'bpfd' in $PATH)
BCC_REMOTE_SSH_PORT=<port> (default 22)

Special priviledges (usually root/sudo access) to run BCC need to be
present only on the remote machine which runs bpfd, the local host
running python/bcc/llvm can run as a normal user.

This backend can also be used on machines with different architectures
than x86 by enabling BCC cross-compilation via the ARCH environment
variable (example ARCH=arm64).

Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
  • Loading branch information
10ne1 committed Apr 5, 2019
1 parent ac42b6e commit 6b3203b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/python/bcc/remote/libremote.py
Expand Up @@ -21,6 +21,7 @@

from .shell import ShellRemote
from .adb import AdbRemote
from .ssh import SshRemote

class BpfCreateMapAttr(ct.Structure):
_fields_ = [("name", ct.c_char_p),
Expand Down
61 changes: 61 additions & 0 deletions src/python/bcc/remote/ssh.py
@@ -0,0 +1,61 @@
# Copyright 2019 Adrian Ratiu <adrian.ratiu@collabora.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os, time, sys
import pexpect as pe

from .shell import ShellRemote

class SshRemote(ShellRemote):
def __init__(self, cmd=None):
"""
Spawn bpfd on a remote machine via ssh and communicate with its
stdin/stdout bound to the ssh socket.
We deliberately do NOT handle ssh authentication and authorization:
make sure your ssh machines are properly set up from a security POV
with passwords securely stored in places like ssh/gpg-agents before
running this code, especially on open networks.
Also make sure the remote user is capable of accessing the bpf syscall.
The local user running BCC doesn't need special privileges.
:param cmd: Command to execute for bpfd. If not specified,
then we default to search for bpfd in the path.
:type cmd: str
"""

if cmd == None:
cmd = 'bpfd'

cmd_env = os.environ.get('BCC_REMOTE_SSH_CMD')
if cmd_env:
cmd = cmd_env

user = os.environ.get('BCC_REMOTE_SSH_USER')
if user == None:
print('SSH backend requires BCC_REMOTE_SSH_USER environment variable definition')
sys.exit(1)

addr = os.environ.get('BCC_REMOTE_SSH_ADDR')
if addr == None:
print('SSH backend requires BCC_REMOTE_SSH_ADDR environment variable definition')
sys.exit(1)

port = os.environ.get('BCC_REMOTE_SSH_PORT')
if port == None:
port = "22"

self.client = pe.spawn("ssh -p {} {}@{} {}".format(port, user, addr, cmd))
self.client.expect('STARTED_BPFD')

0 comments on commit 6b3203b

Please sign in to comment.