In the previous blog post, I set up the development environment on a Windows machine. I further set it up as a ssh
server that can be access by my laptop over the internet. Following is the summarization of some critical steps and relevant materials.
Check installation status of OpenSSH:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Install the OpenSSH Client:
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Install the OpenSSH Server:
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set PowerShell as the default shell: (the shell you enter when ssh into this host)
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
To launch the ssh
server:
Start-Service sshd
Optionally, set ssh
server as automatically start when the computer boots up:
Set-Service -Name sshd -StartupType 'Automatic'
It may also be helpful to confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify:
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
}
Check host username:
How do I find my username and servername for windows SSH server - Super User
$env:USERNAME
Check the IP address (the line of IPv4):
ipconfig
In my case, connect to the Windows host from a MacBook:
ssh <user name>@<ip address>
Enter yes
to add the host to the local machine's host list. Then the terminal will prompt you to enter the password of the user account on the host.
If you can log in successfully, we can further setup the public key so that you don't need to enter password again in the future (and it's more secure in fact):
Developing on Remote Machines using SSH and Visual Studio Code
Key-based authentication in OpenSSH for Windows | Microsoft Learn
OpenSSH Server configuration for Windows | Microsoft Learn
Assuming that you've already generate the key ~/.ssh/id_rsa_dell.pub
. We first add it to local agent. At local terminal run:
ssh-add ~/.ssh/id_rsa_dell
And then deploy (copy) the key to the host. At local terminal run:
export USER_AT_HOST="<user name>@<ip address>"
export PUBKEYPATH="$HOME/.ssh/id_rsa_dell.pub"
ssh $USER_AT_HOST "powershell New-Item -Force -ItemType Directory -Path \"\$HOME\\.ssh\"; Add-Content -Force -Path \"\$HOME\\.ssh\\authorized_keys\" -Value '$(tr -d '\n\r' < "$PUBKEYPATH")'"
P.S. If the account you'd like to log in is an administrator account, you need to run:
export USER_AT_HOST="<user name>@<ip address>"
export PUBKEYPATH="$HOME/.ssh/id_rsa_dell.pub"
ssh $USER_AT_HOST "powershell New-Item -Force -ItemType Directory -Path \"\$HOME\\.ssh\"; Add-Content -Force -Path \"\$env:ProgramData\ssh\administrators_authorized_keys\" -Value '$(tr -d '\n\r' < "$PUBKEYPATH")'"
And then at host run:
icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
After deploying the key to the host, we can configure the host server to enable key authentication. At the host run:
notepad C:\ProgramData\ssh\sshd_config
Make sure that this line is in the file (without #
at the beginning):
PubkeyAuthentication yes
Then restart the ssh
service:
Restart-Service sshd
You should now be able to log in the the host without password.
ssh
via Visual Studio CodeDeveloping on Remote Machines using SSH and Visual Studio Code
Visual Studio Code Remote Development Troubleshooting Tips and Tricks
It's very convenient to ssh
via Visual Studio Code for remote development. However, the host needs to be configured a little bit:
notepad C:\ProgramData\ssh\sshd_config
Make sure that this line is in the file (without #
at the beginning):
AllowTcpForwarding yes
AllowStreamLocalForwarding yes
The most convenient way for remote control a computer over internet may be TeamViewer – The Remote Connectivity Software. However, it suffers from latency and require good network condition. For development purpose, ssh
remote control is more suitable and, with VS Code's ssh
extension, you just have almost the same experience with developing on local machine.
To expose ssh
server to the internet, configuration of the router is needed. The following blog post by chrisjrob provides detail description:
However, for some cases, the router is out of control. For example, your host machine is connected to your school's network. In this case, NAT traversal - Wikipedia is what you need. Here we take cpolar as an example - it provides internet server for free and requires very less configuration. If you prefer to use your own internet server, you can try frp.
Sign up an account and install cpolar
following its instruction:
In terminal, setup token:
cpolar authtoken <your privite token>
Launch TCP tunnel at port 22
:
cpolar tcp 22
Then check the status panel in your cpolar
account webpage. You can find the a tcp tunnel has been setup along with a URL. The URL has two part: domain and port. Try to access it via ssh
:
ssh <user name>@<domain> -p <port>
The TCP tunnel setup via [[#Launch TCP tunnel]] will be expired when the terminal is closed. To set the tunnel to be a background service and automatically launch with reboots, we need to edit cpolar
's configuration file.
Open the configuration file:
notepad ~\.cpolar\cpolar.yml
Edit the configuration. For example:
tunnels:
ssh:
addr: 22
proto: tcp
region: hk
P.S. There are various region options: us,hk,cn,cn_vip.
And then restart cpolar
. The tunnel will be automatically setup:
Restart-Service cpolar