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