Skip to content

Commit d625eae

Browse files
committed
Merge branch '3006.x' into merge/3007.x/3006.x-last-merge
2 parents cea608b + 59ab018 commit d625eae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3673
-4909
lines changed

.github/actions/ssh-tunnel/README.md

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# SSH Tunnel
2+
3+
The ssh-tunnel action will create a reverse tunnel over webrtc to port 22 on the runner.
4+
5+
## Usage
6+
7+
In order to use this action you must have a sdp offer from your local host and a ssh key pair.
8+
Start with creating an sdp offer on your local machine. Provide these values to the ssh-tunnel
9+
action and wait for output from the action with the sdp reply. Provide the reply to the local
10+
rtcforward.py process by pasting it to stdin. If all goes well the local port on your maching
11+
will be forwarded to the ssh port on the runner.
12+
13+
### Getting an sdp offer
14+
15+
To get an sdp offer start rtcforward.py on you local machine with the offer command.
16+
You can also specify which port on the local machine will be used for the tunnel.
17+
18+
``` bash
19+
$ python3 .github/actions/ssh-tunnel/rtcforward.py offer --port 5222
20+
```
21+
22+
rtcforward.py will create an offer an display it to your terminal. (This example offer has been truncated)
23+
After showing the offer the `rtcforward.py` process will wait for a reply.
24+
```
25+
-- offer --
26+
eyJzZHAiOiAidj0wXHJcbm89LSAzOTQ3Mzg4NjUzIDM5NDczODg2NTMgSU4gSVA0IDAuMC4wLjBcclxu
27+
cz0tXHJcbnQ9MCAwXHJcbmE9Z3JvdXA6QlVORExFIDBcclxuYT1tc2lkLXNlbWFudGljOldNUyAqXHJc
28+
bm09YXBwbGljYXRpb24gMzUyNjkgRFRMUy9TQ1RQIDUwMDBcclxuYz1JTiBJUDQgMTkyLjE2OC4wLjIw
29+
IHVkcCAxNjk0NDk4ODE1IDE4NC4xNzkuMjEwLjE1MiAzNTI2OSB0eXAgc3JmbHggcmFkZHIgMTkyLjE2
30+
OC4wLjIwMSBycG9ydCAzNTI2OVxyXG5hPWNhbmRpZGF0ZTozZWFjMzJiZTZkY2RkMTAwZDcwMTFiNWY0
31+
NTo4Qzo2MDoxMTpFQTo3NzpDMTo5RTo1QTo3QzpDQzowRDowODpFQzo2NDowQToxM1xyXG5hPWZpbmdl
32+
cnByaW50OnNoYS01MTIgNjY6MzI6RUQ6MDA6N0I6QjY6NTQ6NzA6MzE6OTA6M0I6Mjg6Q0I6QTk6REU6
33+
MzQ6QjI6NDY6NzE6NUI6MjM6ODA6Nzg6Njg6RDA6QTA6QTg6MjU6QkY6MDQ6ODY6NUY6OTA6QUY6MUQ6
34+
QjA6QzY6ODA6QUY6OTc6QTI6MkM6NDI6QUU6MkI6Q0Q6Mjk6RUQ6MkI6ODc6NTU6ODg6NDY6QTM6ODk6
35+
OEY6ODk6OTE6QTE6QTI6NDM6NTc6M0E6MjZcclxuYT1zZXR1cDphY3RwYXNzXHJcbiIsICJ0eXBlIjog
36+
Im9mZmVyIn0=
37+
-- end offer --
38+
-- Please enter a message from remote party --
39+
```
40+
41+
### Getting an sdp answer
42+
43+
Provide the offer to the ssh-tunnel action. When the action runs, an answer to the offer will be generated.
44+
In the action output you will see that the offer was recieved and the reply in the output.
45+
46+
```
47+
-- Please enter a message from remote party --
48+
-- Message received --
49+
-- reply --
50+
eyJzZHAiOiAidj0wXHJcbm89LSAzOTQ3Mzg3NDcxIDM5NDczODc0NzEgSU4gSVA0IDAuMC4wLjBcclxu
51+
cz0tXHJcbnQ9MCAwXHJcbmE9Z3JvdXA6QlVORExFIDBcclxuYT1tc2lkLXNlbWFudGljOldNUyAqXHJc
52+
bm09YXBwbGljYXRpb24gNTcwMzkgRFRMUy9TQ1RQIDUwMDBcclxuYz1JTiBJUDQgMTkyLjE2OC42NC4x
53+
MFxyXG5hPW1pZDowXHJcbmE9c2N0cG1hcDo1MDAwIHdlYnJ0Yy1kYXRhY2hhbm5lbCA2NTUzNVxyXG5h
54+
MTc6MEI6RTA6OTA6QUM6RjU6RTk6RUI6Q0E6RUE6NTY6REI6NTA6QTk6REY6NTU6MzY6MkM6REI6OUE6
55+
MDc6Mzc6QTM6NDc6NjlcclxuYT1maW5nZXJwcmludDpzaGEtNTEyIDMyOjRDOjk0OkRDOjNFOkU5OkU3
56+
OjNCOjc5OjI4OjZDOjc5OkFEOkVDOjIzOkJDOjRBOjRBOjE5OjlCOjg5OkE3OkE2OjZBOjAwOjJFOkM5
57+
OkE0OjlEOjAwOjM0OjFFOjRDOkVGOjcwOkY5OkNBOjg0OjlEOjcxOjI5OkVCOkIxOkREOkFEOjg5OjUx
58+
OkZFOjhCOjI3OjFDOjFBOkJEOjUxOjQ2OjE4OjBBOjhFOjVBOjI1OjQzOjQzOjZGOkRBXHJcbmE9c2V0
59+
dXA6YWN0aXZlXHJcbiIsICJ0eXBlIjogImFuc3dlciJ9
60+
-- end reply --
61+
```
62+
63+
# Finalizing the tunnel
64+
65+
Paste the sdp reply from the running action into the running `rtcforward.py` process that created the offer.
66+
After receiveing the offer you will see `-- Message received --` and tunnel will be created.
67+
68+
```
69+
-- offer --
70+
eyJzZHAiOiAidj0wXHJcbm89LSAzOTQ3Mzg4NjUzIDM5NDczODg2NTMgSU4gSVA0IDAuMC4wLjBcclxu
71+
cz0tXHJcbnQ9MCAwXHJcbmE9Z3JvdXA6QlVORExFIDBcclxuYT1tc2lkLXNlbWFudGljOldNUyAqXHJc
72+
bm09YXBwbGljYXRpb24gMzUyNjkgRFRMUy9TQ1RQIDUwMDBcclxuYz1JTiBJUDQgMTkyLjE2OC4wLjIw
73+
IHVkcCAxNjk0NDk4ODE1IDE4NC4xNzkuMjEwLjE1MiAzNTI2OSB0eXAgc3JmbHggcmFkZHIgMTkyLjE2
74+
OC4wLjIwMSBycG9ydCAzNTI2OVxyXG5hPWNhbmRpZGF0ZTozZWFjMzJiZTZkY2RkMTAwZDcwMTFiNWY0
75+
NTo4Qzo2MDoxMTpFQTo3NzpDMTo5RTo1QTo3QzpDQzowRDowODpFQzo2NDowQToxM1xyXG5hPWZpbmdl
76+
cnByaW50OnNoYS01MTIgNjY6MzI6RUQ6MDA6N0I6QjY6NTQ6NzA6MzE6OTA6M0I6Mjg6Q0I6QTk6REU6
77+
MzQ6QjI6NDY6NzE6NUI6MjM6ODA6Nzg6Njg6RDA6QTA6QTg6MjU6QkY6MDQ6ODY6NUY6OTA6QUY6MUQ6
78+
QjA6QzY6ODA6QUY6OTc6QTI6MkM6NDI6QUU6MkI6Q0Q6Mjk6RUQ6MkI6ODc6NTU6ODg6NDY6QTM6ODk6
79+
OEY6ODk6OTE6QTE6QTI6NDM6NTc6M0E6MjZcclxuYT1zZXR1cDphY3RwYXNzXHJcbiIsICJ0eXBlIjog
80+
Im9mZmVyIn0=
81+
-- end offer --
82+
-- Please enter a message from remote party --
83+
eyJzZHAiOiAidj0wXHJcbm89LSAzOTQ3Mzg3NDcxIDM5NDczODc0NzEgSU4gSVA0IDAuMC4wLjBcclxu
84+
cz0tXHJcbnQ9MCAwXHJcbmE9Z3JvdXA6QlVORExFIDBcclxuYT1tc2lkLXNlbWFudGljOldNUyAqXHJc
85+
bm09YXBwbGljYXRpb24gNTcwMzkgRFRMUy9TQ1RQIDUwMDBcclxuYz1JTiBJUDQgMTkyLjE2OC42NC4x
86+
MFxyXG5hPW1pZDowXHJcbmE9c2N0cG1hcDo1MDAwIHdlYnJ0Yy1kYXRhY2hhbm5lbCA2NTUzNVxyXG5h
87+
MTc6MEI6RTA6OTA6QUM6RjU6RTk6RUI6Q0E6RUE6NTY6REI6NTA6QTk6REY6NTU6MzY6MkM6REI6OUE6
88+
MDc6Mzc6QTM6NDc6NjlcclxuYT1maW5nZXJwcmludDpzaGEtNTEyIDMyOjRDOjk0OkRDOjNFOkU5OkU3
89+
OjNCOjc5OjI4OjZDOjc5OkFEOkVDOjIzOkJDOjRBOjRBOjE5OjlCOjg5OkE3OkE2OjZBOjAwOjJFOkM5
90+
OkE0OjlEOjAwOjM0OjFFOjRDOkVGOjcwOkY5OkNBOjg0OjlEOjcxOjI5OkVCOkIxOkREOkFEOjg5OjUx
91+
OkZFOjhCOjI3OjFDOjFBOkJEOjUxOjQ2OjE4OjBBOjhFOjVBOjI1OjQzOjQzOjZGOkRBXHJcbmE9c2V0
92+
dXA6YWN0aXZlXHJcbiIsICJ0eXBlIjogImFuc3dlciJ9
93+
-- Message received --
94+
```

.github/actions/ssh-tunnel/action.yml

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: ssh-tunnel
2+
description: SSH Reverse Tunnel
3+
4+
inputs:
5+
public_key:
6+
required: true
7+
type: string
8+
description: Public key to accept for reverse tunnel. Warning, this should not be the public key for the 'private_key' input.
9+
offer:
10+
required: true
11+
type: string
12+
description: RTC offer
13+
debug:
14+
required: false
15+
type: bool
16+
default: false
17+
description: Run sshd with debug enabled.
18+
19+
runs:
20+
using: composite
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- uses: actions/setup-python@v5
25+
with:
26+
python-version: '3.10'
27+
28+
- name: Install ssh
29+
if: ${{ runner.os == 'Windows' }}
30+
shell: powershell
31+
run: |
32+
python3.exe -m pip install requests
33+
python3.exe .github/actions/ssh-tunnel/installssh.py
34+
35+
- name: Start SSH
36+
shell: bash
37+
run: |
38+
if [ "$RUNNER_OS" = "Windows" ]; then
39+
powershell.exe -command "Start-Service sshd"
40+
elif [ "$RUNNER_OS" = "macOS" ]; then
41+
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
42+
else
43+
sudo systemctl start ssh
44+
fi
45+
46+
- name: Show sshd configuration
47+
shell: bash
48+
run: |
49+
if [ "$RUNNER_OS" = "Linux" ]; then
50+
cat /etc/ssh/sshd_config
51+
elif [ "$RUNNER_OS" = "macOS" ]; then
52+
cat /private/etc/ssh/sshd_config
53+
else
54+
cat "C:\ProgramData\ssh\sshd_config"
55+
fi
56+
57+
- name: Add ssh public key
58+
shell: bash
59+
run: |
60+
if [ "$RUNNER_OS" = "Linux" ]; then
61+
mkdir -p /home/runner/.ssh
62+
chmod 700 /home/runner/.ssh
63+
touch /home/runner/.ssh/authorized_keys
64+
echo "${{ inputs.public_key }}" | tee -a /home/runner/.ssh/authorized_keys
65+
elif [ "$RUNNER_OS" = "macOS" ]; then
66+
mkdir -p /Users/runner/.ssh
67+
chmod 700 /Users/runner/.ssh
68+
touch /Users/runner/.ssh/authorized_keys
69+
echo "${{ inputs.public_key }}" | tee -a /Users/runner/.ssh/authorized_keys
70+
else
71+
echo "${{ inputs.public_key }}" | tee -a "C:\ProgramData\ssh\administrators_authorized_keys"
72+
fi
73+
74+
- name: Stop SSHD
75+
if: ${{ inputs.debug }}
76+
shell: bash
77+
run: |
78+
if [ "${{ inputs.debug }}" = "true" ]; then
79+
if [ "$RUNNER_OS" = "Windows" ]; then
80+
powershell.exe -command "Stop-Service sshd"
81+
elif [ "$RUNNER_OS" = "macOS" ]; then
82+
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
83+
else
84+
sudo systemctl stop ssh
85+
fi
86+
fi
87+
88+
- name: Create rtc tunnel
89+
shell: bash
90+
run: |
91+
if [ "${{ inputs.debug }}" = "true" ]; then
92+
if [ "$RUNNER_OS" = "Windows" ]; then
93+
./OpenSSH-Win64/sshd.exe -d &
94+
elif [ "$RUNNER_OS" = "macOS" ]; then
95+
sudo /usr/sbin/sshd -d &
96+
else
97+
sudo mkdir -p /run/sshd
98+
sudo chmod 755 /run/sshd
99+
sudo /usr/sbin/sshd -d &
100+
fi
101+
fi
102+
if [ "$RUNNER_OS" = "Windows" ]; then
103+
python3 -m pip install aiortc
104+
else
105+
python3 -m pip install aiortc uvloop
106+
fi
107+
echo '${{ inputs.offer }}' | python .github/actions/ssh-tunnel/rtcforward.py --port 22 answer
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
"""
3+
4+
import pathlib
5+
import subprocess
6+
import zipfile
7+
8+
import requests
9+
10+
fwrule = """
11+
New-NetFirewallRule `
12+
-Name sshd `
13+
-DisplayName 'OpenSSH SSH Server' `
14+
-Enabled True `
15+
-Direction Inbound `
16+
-Protocol TCP `
17+
-Action Allow `
18+
-LocalPort 22 `
19+
-Program "{}"
20+
"""
21+
22+
23+
def start_ssh_server():
24+
"""
25+
Pretty print the GH Actions event.
26+
"""
27+
resp = requests.get(
28+
"https://github.com/PowerShell/Win32-OpenSSH/releases/download/v9.8.1.0p1-Preview/OpenSSH-Win64.zip",
29+
allow_redirects=True,
30+
)
31+
with open("openssh.zip", "wb") as fp:
32+
fp.write(resp.content)
33+
with zipfile.ZipFile("openssh.zip") as fp:
34+
fp.extractall()
35+
install_script = pathlib.Path("./OpenSSH-Win64/install-sshd.ps1").resolve()
36+
print(f"{install_script}")
37+
subprocess.call(["powershell.exe", f"{install_script}"])
38+
with open("fwrule.ps1", "w") as fp:
39+
fp.write(fwrule.format(install_script.parent / "sshd.exe"))
40+
subprocess.call(["powershell.exe", f"fwrule.ps1"])
41+
42+
43+
if __name__ == "__main__":
44+
start_ssh_server()

0 commit comments

Comments
 (0)