1#!/bin/bash 2 3# oe-git-proxy is a simple tool to be via GIT_PROXY_COMMAND. It uses socat 4# to make SOCKS5 or HTTPS proxy connections. 5# It uses ALL_PROXY or all_proxy or http_proxy to determine the proxy server, 6# protocol, and port. 7# It uses NO_PROXY to skip using the proxy for a comma delimited list of 8# hosts, host globs (*.example.com), IPs, or CIDR masks (192.168.1.0/24). It 9# is known to work with both bash and dash shells. 10# 11# Example ALL_PROXY values: 12# ALL_PROXY=socks://socks.example.com:1080 13# ALL_PROXY=https://proxy.example.com:8080 14# 15# Copyright (c) 2013, Intel Corporation. 16# 17# SPDX-License-Identifier: GPL-2.0-only 18# 19# AUTHORS 20# Darren Hart <dvhart@linux.intel.com> 21 22# disable pathname expansion, NO_PROXY fields could start with "*" or be it 23set -f 24 25if [ $# -lt 2 -o "$1" = '--help' -o "$1" = '-h' ] ; then 26 echo 'oe-git-proxy: error: the following arguments are required: host port' 27 echo 'Usage: oe-git-proxy host port' 28 echo '' 29 echo 'OpenEmbedded git-proxy - a simple tool to be used via GIT_PROXY_COMMAND.' 30 echo 'It uses socat to make SOCKS or HTTPS proxy connections.' 31 echo 'It uses ALL_PROXY to determine the proxy server, protocol, and port.' 32 echo 'It uses NO_PROXY to skip using the proxy for a comma delimited list' 33 echo 'of hosts, host globs (*.example.com), IPs, or CIDR masks (192.168.1.0/24).' 34 echo 'It is known to work with both bash and dash shells.runs native tools' 35 echo '' 36 echo 'arguments:' 37 echo ' host proxy host to use' 38 echo ' port proxy port to use' 39 echo '' 40 echo 'options:' 41 echo ' -h, --help show this help message and exit' 42 echo '' 43 exit 2 44fi 45 46# Locate the netcat binary 47if [ -z "$SOCAT" ]; then 48 SOCAT=$(which socat 2>/dev/null) 49 if [ $? -ne 0 ]; then 50 echo "ERROR: socat binary not in PATH" 1>&2 51 exit 1 52 fi 53fi 54METHOD="" 55 56# Test for a valid IPV4 quad with optional bitmask 57valid_ipv4() { 58 echo $1 | egrep -q "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}(/(3[0-2]|[1-2]?[0-9]))?$" 59 return $? 60} 61 62# Convert an IPV4 address into a 32bit integer 63ipv4_val() { 64 IP="$1" 65 SHIFT=24 66 VAL=0 67 for B in $( echo "$IP" | tr '.' ' ' ); do 68 VAL=$(($VAL+$(($B<<$SHIFT)))) 69 SHIFT=$(($SHIFT-8)) 70 done 71 echo "$VAL" 72} 73 74# Determine if two IPs are equivalent, or if the CIDR contains the IP 75match_ipv4() { 76 CIDR=$1 77 IP=$2 78 79 if [ -z "${IP%%$CIDR}" ]; then 80 return 0 81 fi 82 83 # Determine the mask bitlength 84 BITS=${CIDR##*/} 85 [ "$BITS" != "$CIDR" ] || BITS=32 86 if [ -z "$BITS" ]; then 87 return 1 88 fi 89 90 IPVAL=$(ipv4_val $IP) 91 IP2VAL=$(ipv4_val ${CIDR%%/*}) 92 93 # OR in the unmasked bits 94 for i in $(seq 0 $((32-$BITS))); do 95 IP2VAL=$(($IP2VAL|$((1<<$i)))) 96 IPVAL=$(($IPVAL|$((1<<$i)))) 97 done 98 99 if [ $IPVAL -eq $IP2VAL ]; then 100 return 0 101 fi 102 return 1 103} 104 105# Test to see if GLOB matches HOST 106match_host() { 107 HOST=$1 108 GLOB=$2 109 110 if [ -z "${HOST%%*$GLOB}" ]; then 111 return 0 112 fi 113 114 # Match by netmask 115 if valid_ipv4 $GLOB; then 116 for HOST_IP in $(getent ahostsv4 $HOST | grep ' STREAM ' | cut -d ' ' -f 1) ; do 117 if valid_ipv4 $HOST_IP; then 118 match_ipv4 $GLOB $HOST_IP 119 if [ $? -eq 0 ]; then 120 return 0 121 fi 122 fi 123 done 124 fi 125 126 return 1 127} 128 129# If no proxy is set or needed, just connect directly 130METHOD="TCP:$1:$2" 131 132[ -z "${ALL_PROXY}" ] && ALL_PROXY=$all_proxy 133[ -z "${ALL_PROXY}" ] && ALL_PROXY=$http_proxy 134 135if [ -z "$ALL_PROXY" ]; then 136 exec $SOCAT STDIO $METHOD 137fi 138 139# Connect directly to hosts in NO_PROXY 140for H in $( echo "$NO_PROXY" | tr ',' ' ' ); do 141 if match_host $1 $H; then 142 exec $SOCAT STDIO $METHOD 143 fi 144done 145 146# Proxy is necessary, determine protocol, server, and port 147# extract protocol 148PROTO=${ALL_PROXY%://*} 149# strip protocol:// from string 150ALL_PROXY=${ALL_PROXY#*://} 151# extract host & port parts: 152# 1) drop username/password 153PROXY=${ALL_PROXY##*@} 154# 2) remove optional trailing /? 155PROXY=${PROXY%%/*} 156# 3) extract optional port 157PORT=${PROXY##*:} 158if [ "$PORT" = "$PROXY" ]; then 159 PORT="" 160fi 161# 4) remove port 162PROXY=${PROXY%%:*} 163 164# extract username & password 165PROXYAUTH="${ALL_PROXY%@*}" 166[ "$PROXYAUTH" = "$ALL_PROXY" ] && PROXYAUTH= 167[ -n "${PROXYAUTH}" ] && PROXYAUTH=",proxyauth=${PROXYAUTH}" 168 169if [ "$PROTO" = "socks" ] || [ "$PROTO" = "socks4a" ]; then 170 if [ -z "$PORT" ]; then 171 PORT="1080" 172 fi 173 METHOD="SOCKS4A:$PROXY:$1:$2,socksport=$PORT" 174elif [ "$PROTO" = "socks4" ]; then 175 if [ -z "$PORT" ]; then 176 PORT="1080" 177 fi 178 METHOD="SOCKS4:$PROXY:$1:$2,socksport=$PORT" 179else 180 # Assume PROXY (http, https, etc) 181 if [ -z "$PORT" ]; then 182 PORT="8080" 183 fi 184 METHOD="PROXY:$PROXY:$1:$2,proxyport=${PORT}${PROXYAUTH}" 185fi 186 187exec $SOCAT STDIO "$METHOD" 188