A GIT_SSH_COMMAND-compatible client and gateway that allows the gateway to apply protocol-aware
policies to SSH sessions without breaking key authentication.
Without this software (or something very much like it), you cannot prevent a host that needs to upload/download software from a shared git server (e.g. GitHub/GitLab) from uploading/downloading software from organizations, users, and repositories you do not control. This is a data exfiltration and malware risk.
Because SSH, and by extension Git, often uses key-based authentication, the traffic inside of the SSH session cannot be inspected by traditional proxies using "break-and-inspect". This setup gets around that limitation by having the client securely forward its client-to-server key to the Gateway. Using that key, the Gateway can apply policy on encrypted SSH packets, applying limits on:
- Remote forwarding, including limitations on addresses/ports
- Local forwarding, including limitations on addresses/ports
- PTY allocation
- X11 forwarding
- Shell execution
- Arbitrary subsystems (e.g. sftp)
- Commands ran
The ability to limit commands ran also gives the Gateway the ability to apply policy on Git traffic, permitting or denying downloading/uploading data based on hostname and Git path.
Git can be configured globally with the gateway client using
core.sshCommand:
git config --global core.sshCommand \
'/usr/local/bin/git-gateway-ssh --gateway jump@gateway.example.com:22'
git clone git@github.com:example/repository.git- Make the software and a test host key for the gateway
make all && make host-key- In one window, run the server:
# Replace authorized key with whatever ssh key you actually have available
bin/ssh-gateway -authorized-key ~/.ssh/id_rsa.pub -host-key ./gateway_host_ed25519- Run git with the custom command:
# Should work - policy permits this repo
GIT_GATEWAY_INSECURE_HOST_KEY='true' GIT_SSH_COMMAND='bin/git-gateway-s
sh --gateway jump@127.0.0.1:2222' git pull
# Should fail - policy default denies
GIT_GATEWAY_INSECURE_HOST_KEY='true' GIT_SSH_COMMAND='bin/git-gateway-ssh --gateway jump@127.0.0.1:2222' git clone git@github.com:git/git.gitExample rejection:
micrictor@laptop:~/git-gateway$ GIT_GATEWAY_INSECURE_HOST_KEY='true' GIT_SSH_COMMAND='bin/git-gateway-ssh --gateway jump@127.0.0.1:2222' git clone git@github.com:git/git.git
Cloning into 'git'...
git-gateway-ssh: gateway policy denied request: Git policy denied fetch for git/git on github.com
git-gateway-ssh: gateway policy denied request: Git policy denied fetch for git/git on github.com
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
- Deploy system Git config to use the custom client.
- Install the gateway trusted key/certificate
- In
/etc/gitconfig(or similar file) on all endpoints, add:
[core]
sshCommand = '/path/to/git-gateway-ssh --gateway jump@yourgateway:22'
- Via host or network firewalls, block SSH traffic directly to all "known" public Git servers (GitHub/GitLab/Bitbucket/Gitee/Codeberg), forcing the use of the proxy to connect to those hosts.
A more agressive approach would be to block ALL ssh traffic that does not route via the Gateway. For this to work without breaking SSH, that would require you to:
- Alter the gateway logic to only conditionally allow "failopen" when the destination IPs are not known git servers (i.e. not GitHub/GitLab/Bitbucket/Codeberg/etc)
- Potential advantage of this is that you could use your "onboarded" git clients to continously build a set of known "git server" IPs.
- Build a patched version of an SSH client that supports the gateway's required key-forwarding, giving you the ability to apply SSH-aware policy to all of your SSH traffic.