The best tool ever for connect remote VM desktop via Citrix VPN/Gateway by one click
Cron:
- No resident app needed, no resource require after connected, no garbage file left(.rdp files)
- One-Click to connect to remote VM, fast, simple, easy
- Enable change multi-monitor settings, you can force single monitor or dual monitor for remote desktop
- Self-signed certification supported
- Reduce Citrix gateway web portal resource usage
优点:
Citrix Gateway远程桌面网关(NetScaler AAA),连接远程虚拟机VM,需要打开网页,登录然后再下载RDP文件,然后打开RDP文件,非常繁琐,并且由于每次都下载RDP文件,导致download目录下积累了大量的.rdp文件,变成垃圾文件,十分恶心。
我们可以使用以下脚本shell(vm.sh,可以用 git bash运行,如果没有自签名证书,请修改opts去掉"--insecure --cert XXXX.pfx:XXXX --cert-type P12",并且git for windows版本应该低于2.33运行,高版本可能出现openssl无法打开证书的问题,或者你使用openssl 3.0以上证书也可以使用新版本),实现一键登录VM(Citrix Gateway 2016):
#!/bin/bash
version=1.2
echo "Citrix Gateway VM 连接工具 v$version"
echo "Copyright© Richard, 2024"
echo "本工具不驻留内存,不消耗任何额外的资源。"
highlight() {
echo -e "\033[$1m$2\033[0m"
}
uriencode() {
curl -Gso /dev/null -w %{url_effective} --data-urlencode "data=$1" "0.0.0.0" | cut -d'=' -f2
}
function input() {
local buf=""
while true; do
read -p "$1" $2 buf
if [ -z "$buf" ]; then
highlight 41 "输入不能为空,请重新输入。" >&2
else
break
fi
done
echo $buf
}
check() {
if [ $? -ne 0 ]; then
highlight 41 "失败"
read -n 1 -s -r -p "按任意键继续..."
exit 1
fi
}
if [[ "$1" == "-h" || "$1" == "/?" || "$1" == "--help" ]]; then
echo "用法: $0 [-h]"
echo "例如:"
echo " $0 初始化或一键连接"
echo " $0 -h 显示帮助"
echo "初始化只会运行一次,请勿中断初始化过程"
highlight 41 "若有问题可删除 config.dat, headers.txt 重新初始化"
echo "可自定义headers.txt,以适配特殊情况"
exit 0
fi
openssl_version=$(openssl version | awk '{print $2}')
if [[ ! "$openssl_version" < "3.0" ]]; then
highlight 41 "不支持 Openssl 3.0及以上版本,当前版本 $openssl_version。";
echo "请安装 git v2.41.0 及以下版本来运行本脚本";
read -n 1 -s -r -p "按任意键继续..."
exit 1
fi
cd "$(dirname "$(readlink -f "$0")")"
if [ -f config.dat ]; then
source config.dat
if [ -z "$version" ] || [ "$(awk 'BEGIN{print ("'$version'" < 1.2) ? "true" : "false" }')" == "true" ]; then
rm config.dat
fi
fi
if [ -f config.dat ]; then
source config.dat
salt=$(echo "$salt" | base64 -d)
password=$(echo "$key" | openssl enc -d -aes-256-cbc -pbkdf2 -base64 -k "$COMPUTERNAME$salt")
else
highlight 41 "开始初始化配置,若有问题可删除 config.dat 重新初始化"
read -p "请输入Citrix网关地址(默认: https://www.citrix_gateway.com): " server
server=${server:-https://www.citrix_gateway.com}
user=$(input "用户名(corp id): ")
password=$(input "请输入密码, \字符用\\\\替代: " -s)
password=$(uriencode "$password")
echo
read -p "目标VM IP地址(若有多个VM必输,否则可选): " ip
read -p "多显示器支持,多个用逗号分隔(例如0,1表示在第1、2个显示器显示,不输表示单显示器模式): " monitors
salt=$(openssl rand -hex 10)
key=$(echo "$password" | openssl enc -aes-256-cbc -pbkdf2 -base64 -k "$COMPUTERNAME$salt")
salt=$(echo -n "$salt" | base64)
echo "server=$server" > config.dat
echo "user=$user" >> config.dat
echo "ip=$ip" >> config.dat
echo "salt=$salt" >> config.dat
echo "key=$key" >> config.dat
echo "version=$version" >> config.dat
echo "monitors=$monitors" >> config.dat
fi
if [ -f desktop.rdp ]; then
rm desktop.rdp
fi
if [ ! -f headers.txt ]; then
cat <<EOF >headers.txt
Accept: application/xml, text/xml, */*; q=0.01
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Origin: $server
Pragma: no-cache
Referer: $server
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0
X-Citrix-AM-CredentialTypes: none, username, domain, password, newpassword, passcode, savecredentials, textcredential, webview, nsg-epa, nsg-x1, nsg-setclient, nsg-eula, nsg-tlogin, nsg-fullvpn, nsg-hidden, nsg-auth-failure, nsg-auth-success, nsg-epa-success, nsg-l20n, GoBack, nf-recaptcha, ns-dialogue, nf-gw-test, nf-poll, nsg_qrcode, nsg_manageotp, negotiate, nsg_push, nsg_push_otp, nf_sspr_rem
X-Citrix-AM-LabelTypes: none, plain, heading, information, warning, error, confirmation, image, nsg-epa, nsg-epa-failure, nsg-login-label, tlogin-failure-msg, nsg-tlogin-heading, nsg-tlogin-single-res, nsg-tlogin-multi-res, nsg-tlogin, nsg-login-heading, nsg-fullvpn, nsg-l20n, nsg-l20n-error, certauth-failure-msg, dialogue-label, nsg-change-pass-assistive-text, nsg_confirmation, nsg_kba_registration_heading, nsg_email_registration_heading, nsg_kba_validation_question, nsg_sspr_success, nf-manage-otp
X-Citrix-IsUsingHTTPS: Yes
X-Requested-With: XMLHttpRequest
sec-ch-ua: "Microsoft Edge";v="123", "Not:A-Brand";v="8", "Chromium";v="123"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
EOF
fi
opts="-s -H @headers.txt --insecure --cert xxx.pfx:xxx --cert-type P12"
echo 获取鉴权环境...
curl $opts -i -o response.txt -X 'POST' "$server/nf/auth/getAuthenticationRequirements.do"
check
url=$(grep -o '<PostBack>[^<]*</PostBack>' response.txt | sed 's/<\/\?PostBack>//g')
context=$(echo "$url" | sed 's/\/nf\/auth\/doCert\.do?//')
echo url=$url
echo
echo 获取令牌 NSC_TMAS...
curl $opts -i -o response.txt -X 'POST' "$server$url" --data-raw \"$context\"
check
NSC_TMAS=$(grep -o 'NSC_TMAS=[^;]*' response.txt | sed 's/NSC_TMAS=//')
cookie="NSC_TMAS=$NSC_TMAS"
echo $cookie
echo
echo 开始鉴权...
curl $opts -i -o response.txt -X 'POST' "$server/nf/auth/doAuthentication.do" -b "$cookie" --data-raw "login=$user&passwd=$password&domain=ss_corp&loginBtn=Log+On&StateContext="
check
NSC_AAAC=$(grep -o 'NSC_AAAC=[^;]*' response.txt | sed 's/NSC_AAAC=//')
cookie="NSC_SAMS=Strict;NSC_AAAC=$NSC_AAAC"
StateContext=$(grep -o '<StateContext>[^<]*</StateContext>' response.txt | sed 's/<\/\?StateContext>//g')
echo $cookie
echo Context: $StateContext
echo
echo 配置客户端...
curl $opts -i -o response.txt -X 'POST' "$server/p/u/setClient.do" -b "$cookie" --data-raw "nsg-setclient=cvpn&StateContext=$StateContext"
check
NSC_TEMP=$(grep -o 'NSC_TEMP=[^;]*' response.txt | sed 's/NSC_TEMP=//')
cookie="NSC_SAMS=Strict; NSC_AAAC=$NSC_AAAC; NSC_TEMP=$NSC_TEMP"
echo $cookie
echo
echo 获取远程VM地址清单...
curl $opts -i -o response.txt -X 'GET' "$server/cgi/resources/list" -b "$cookie"
content=$(grep -o '"content":"[^"]*"' response.txt | awk -F '"' '{print $4}')
check
echo $content
echo
if [ -z "$ip" ]; then
rdpUrl="$content"
else
echo 抽取 $ip 对应的地址...
rdpUrl=$(echo "$content" | awk -v ip="$ip" '{for(i=1;i<=NF;i++) if($i ~ ip) print $i}')
fi
echo 下载RDP配置文件: $rdpUrl
curl $opts -o desktop.rdp -X 'GET' "$rdpUrl" -b "$cookie"
check
echo 更改为单个桌面连接...
echo >>desktop.rdp
if [ ! -z "$monitors" ]; then
echo "selectedmonitors:s:$monitors">>desktop.rdp
fi
echo "compression:i:1">>desktop.rdp
echo "username:s:$user">>desktop.rdp
echo "domain:s:corpdev">>desktop.rdp
echo "desktopscalefactor:i:100">>desktop.rdp
sed -i 's/redirectclipboard:i:0/redirectclipboard:i:1/g' desktop.rdp
if [ -z "$monitors" ]; then
sed -i 's/use multimon:i:1/use multimon:i:0/g' desktop.rdp
fi
echo 等待远程服务器配置就绪...
highlight 44\;97 "若失败请手动打开 desktop.rdp 或重试..."
highlight 44\;97 "请勿勾选记住密码,因为连接每次都不一样"
sleep 10
echo 启动远程桌面
$SYSTEMROOT\\System32\\cmd.exe //c start mstsc //admin desktop.rdp &
sleep 1
rm response.txt
下载的Citrix Gateway RDP文件示例:
redirectclipboard:i:0
redirectdrives:i:0
redirectprinters:i:0
redirectcomports:i:0
redirectpnpdevices:i:0
keyboardhook:i:2
audiocapturemode:i:0
videoplaybackmode:i:1
use multimon:i:0
negotiate security layer:i:1
enablecredsspsupport:i:1
authentication level:i:0
full address:s:www.citrix_gateway_server.com:443
loadbalanceinfo:s:52bc4a0fb4ed87904d57f6896212fd79a20a1b63c5fa4f73a477d0e339af5ba23c72
运行效果:
错误处理
- schannel: AcquireCredentialsHandle failed: SEC_E_NO_CREDENTIALS
这是因为git for windows 使用了 openssl 3.x 版本编译导致的,从 git for windows 3.41.0 以上版本开始,用的是 openssl 3.x 编译的,openssl 3.x 很多老的 provider 不提供了,而你提供的证书是老版本(Openssl 1.x编译的),所以一些证书不兼容。请使用 git for windows 3.41.0 及以下版本运行。或者试着用新版本openssl 制作证书。
如下图:
此时需要核对用户名和密码是否正确,可以删除 config.dat 后重试。密码是网页登录密码,不是包含 $ 的那个密码!!!
上图是没有配置好IP导致的,请打开config.dat,配置IP地址即可。
这是因为账户属于特殊账户,和普通用户流程不一样,暂时不支持。你可以自己根据实际情况调整脚本代码。