From 5ea25e6736430ab5b8439d11b2e9a837a803771b Mon Sep 17 00:00:00 2001 From: Septs Date: Mon, 25 May 2020 00:48:43 +0800 Subject: [PATCH] Add `shell-proxy` plugin (#8692) --- plugins/shell-proxy/README.md | 52 ++++++++++++++++ plugins/shell-proxy/proxy.py | 72 ++++++++++++++++++++++ plugins/shell-proxy/shell-proxy.plugin.zsh | 16 +++++ plugins/shell-proxy/ssh-agent.py | 16 +++++ plugins/shell-proxy/ssh-proxy.py | 18 ++++++ 5 files changed, 174 insertions(+) create mode 100644 plugins/shell-proxy/README.md create mode 100755 plugins/shell-proxy/proxy.py create mode 100644 plugins/shell-proxy/shell-proxy.plugin.zsh create mode 100755 plugins/shell-proxy/ssh-agent.py create mode 100755 plugins/shell-proxy/ssh-proxy.py diff --git a/plugins/shell-proxy/README.md b/plugins/shell-proxy/README.md new file mode 100644 index 000000000..6f2cd13e0 --- /dev/null +++ b/plugins/shell-proxy/README.md @@ -0,0 +1,52 @@ +# Shell Proxy oh-my-zsh plugin + +This a pure user-space program, shell-proxy setter, written Python3 and Bash. + +100% only no side-effects, only effect **environment variables** and **aliases** + +## Key feature + +- Support Ubuntu, Archlinux, etc (Linux) +- Support macOS +- Support git via based-`$GIT_SSH` +- Support ssh, sftp, scp, slogin and ssh-copy-id via based-`alias` +- Built-in Auto-complete + +## Usage + +Method 1: + +`$DEFAULT_PROXY` is the proxy URL you will set + +Method 2: + +Write a program to `$HOME/.config/proxy` in the file. + +Example program: + +```bash +#!/bin/bash +# The file path: $HOME/.config/proxy +if [[ "$OSTYPE" == "darwin"* ]]; then + echo "http://127.0.0.1:6152" # Surge Mac +else + echo "http://127.0.0.1:8123" # polipo +fi +``` + +Method 3: + +The working path of **Method 2** can be changed via `$CONFIG_PROXY` + +## Reference + +- `$GIT_SSH`: +- OpenSSH manual: + +## Maintainer + +- + +## The oh-my-zsh plugin (shell-proxy) + +Public Domain diff --git a/plugins/shell-proxy/proxy.py b/plugins/shell-proxy/proxy.py new file mode 100755 index 000000000..2b62f6cb5 --- /dev/null +++ b/plugins/shell-proxy/proxy.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +import os +import sys +from subprocess import check_output, list2cmdline + +cwd = os.path.dirname(__file__) +ssh_agent = os.path.join(cwd, "ssh-agent.py") +user_proxy = os.environ.get("CONFIG_PROXY", os.path.expandvars("$HOME/.config/proxy")) + + +def get_http_proxy(): + if "DEFAULT_PROXY" in os.environ: + return os.environ["DEFAULT_PROXY"] + if os.path.isfile(user_proxy): + return check_output(user_proxy).decode("utf-8").strip() + raise Exception("Not found, Proxy configuration") + + +def make_proxies(url: str): + proxies = {"%s_PROXY" % _: url for _ in ("HTTP", "HTTPS", "FTP", "RSYNC", "ALL")} + proxies.update({name.lower(): value for (name, value) in proxies.items()}) + proxies["GIT_SSH"] = ssh_agent + return proxies + + +def merge(mapping: dict): + return ("%s=%s" % _ for _ in mapping.items()) + + +class CommandSet: + proxies = make_proxies(get_http_proxy()) + aliases = { + _: "env NAME=%s %s" % (_, ssh_agent) + for _ in ("ssh", "sftp", "scp", "slogin", "ssh-copy-id") + } + + def enable(self): + cmdline("export", *merge(self.proxies)) + cmdline("alias", *merge(self.aliases)) + + def disable(self): + cmdline("unset", *self.proxies.keys()) + cmdline("unalias", *self.aliases.keys()) + + def status(self): + proxies = ( + "%11s = %s" % (name, os.environ[name]) + for name in self.proxies.keys() + if name in os.environ + ) + for _ in proxies: + cmdline("echo", _) + + def usage(self): + cmdline("echo", "usage: proxy {enable,disable,status}") + self.status() + + +def cmdline(*items): + print(list2cmdline(items)) + + +def main(): + command = CommandSet() + if len(sys.argv) == 1: + command.usage() + sys.exit(-1) + getattr(command, sys.argv[1], command.usage)() + + +if __name__ == "__main__": + main() diff --git a/plugins/shell-proxy/shell-proxy.plugin.zsh b/plugins/shell-proxy/shell-proxy.plugin.zsh new file mode 100644 index 000000000..fd0e2fe79 --- /dev/null +++ b/plugins/shell-proxy/shell-proxy.plugin.zsh @@ -0,0 +1,16 @@ +#!/usr/bin/bash +# shellcheck disable=SC1090 + +__PROXY__="${0:A:h}/proxy.py" + +proxy() { + source <("$__PROXY__" "$1") +} + +_proxy() { + local -r commands=('enable' 'disable' 'status') + compset -P '*,' + compadd -S '' "${commands[@]}" +} + +compdef '_proxy' 'proxy' diff --git a/plugins/shell-proxy/ssh-agent.py b/plugins/shell-proxy/ssh-agent.py new file mode 100755 index 000000000..61cf84c0b --- /dev/null +++ b/plugins/shell-proxy/ssh-agent.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys + +ssh_proxy = os.path.join(os.path.dirname(__file__), "ssh-proxy.py") + +argv = [ + os.environ.get("NAME", "ssh"), + "-o", + "ProxyCommand={} %h %p".format(ssh_proxy), + "-o", + "Compression=yes", +] + +subprocess.call(argv + sys.argv[1:], env=os.environ) diff --git a/plugins/shell-proxy/ssh-proxy.py b/plugins/shell-proxy/ssh-proxy.py new file mode 100755 index 000000000..5efd5fd21 --- /dev/null +++ b/plugins/shell-proxy/ssh-proxy.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import os +import subprocess +import sys +import urllib.parse + +proxy = next(os.environ[_] for _ in ("HTTP_PROXY", "HTTPS_PROXY") if _ in os.environ) +argv = [ + "nc", + "-X", + "connect", + "-x", + urllib.parse.urlparse(proxy).netloc, # proxy-host:proxy-port + sys.argv[1], # host + sys.argv[2], # port +] + +subprocess.call(argv)