-
-
Save samhocevar/00eec26d9e9988d080ac to your computer and use it in GitHub Desktop.
#!/bin/sh | |
# | |
# msys2-sshd-setup.sh — configure sshd on MSYS2 and run it as a Windows service | |
# | |
# Please report issues and/or improvements to Sam Hocevar <sam@hocevar.net> | |
# | |
# Prerequisites: | |
# — MSYS2 itself: http://sourceforge.net/projects/msys2/ | |
# — admin tools: pacman -S openssh cygrunsrv mingw-w64-x86_64-editrights | |
# | |
# This script is a cleaned up and improved version of the procedure initially | |
# found at https://ghc.haskell.org/trac/ghc/wiki/Building/Windows/SSHD | |
# | |
# Gotchas: | |
# — the log file will be /var/log/msys2_sshd.log | |
# — if you get error “sshd: fatal: seteuid XXX : No such device or address” | |
# in the logs, try “passwd -R” (with admin privileges) | |
# | |
# Changelog: | |
# 27 Jun 2019 — rename service to msys2_sshd to avoid conflicts with Windows OpenSSH | |
# — use mkgroup.exe as suggested in the comments | |
# — fix a problem with CRLF and grep | |
# 24 Aug 2015 — run server with -e to redirect logs to /var/log/sshd.log | |
# | |
set -e | |
# | |
# Configuration | |
# | |
PRIV_USER=sshd_server | |
PRIV_NAME="Privileged user for sshd" | |
UNPRIV_USER=sshd # DO NOT CHANGE; this username is hardcoded in the openssh code | |
UNPRIV_NAME="Privilege separation user for sshd" | |
EMPTY_DIR=/var/empty | |
# | |
# Check installation sanity | |
# | |
if ! /mingw64/bin/editrights -h >/dev/null; then | |
echo "ERROR: Missing 'editrights'. Try: pacman -S mingw-w64-x86_64-editrights." | |
exit 1 | |
fi | |
if ! cygrunsrv -v >/dev/null; then | |
echo "ERROR: Missing 'cygrunsrv'. Try: pacman -S cygrunsrv." | |
exit 1 | |
fi | |
if ! ssh-keygen -A; then | |
echo "ERROR: Missing 'ssh-keygen'. Try: pacman -S openssh." | |
exit 1 | |
fi | |
# | |
# The privileged cyg_server user | |
# | |
# Some random password; this is only needed internally by cygrunsrv and | |
# is limited to 14 characters by Windows (lol) | |
tmp_pass="$(tr -dc 'a-zA-Z0-9' < /dev/urandom | dd count=14 bs=1 2>/dev/null)" | |
# Create user | |
add="$(if ! net user "${PRIV_USER}" >/dev/null; then echo "//add"; fi)" | |
if ! net user "${PRIV_USER}" "${tmp_pass}" ${add} //fullname:"${PRIV_NAME}" \ | |
//homedir:"$(cygpath -w ${EMPTY_DIR})" //yes; then | |
echo "ERROR: Unable to create Windows user ${PRIV_USER}" | |
exit 1 | |
fi | |
# Add user to the Administrators group if necessary | |
admingroup="$(mkgroup -l | awk -F: '{if ($2 == "S-1-5-32-544") print $1;}')" | |
if ! (net localgroup "${admingroup}" | grep -q '^'"${PRIV_USER}"'\>'); then | |
if ! net localgroup "${admingroup}" "${PRIV_USER}" //add; then | |
echo "ERROR: Unable to add user ${PRIV_USER} to group ${admingroup}" | |
exit 1 | |
fi | |
fi | |
# Infinite passwd expiry | |
passwd -e "${PRIV_USER}" | |
# set required privileges | |
for flag in SeAssignPrimaryTokenPrivilege SeCreateTokenPrivilege \ | |
SeTcbPrivilege SeDenyRemoteInteractiveLogonRight SeServiceLogonRight; do | |
if ! /mingw64/bin/editrights -a "${flag}" -u "${PRIV_USER}"; then | |
echo "ERROR: Unable to give ${flag} rights to user ${PRIV_USER}" | |
exit 1 | |
fi | |
done | |
# | |
# The unprivileged sshd user (for privilege separation) | |
# | |
add="$(if ! net user "${UNPRIV_USER}" >/dev/null; then echo "//add"; fi)" | |
if ! net user "${UNPRIV_USER}" ${add} //fullname:"${UNPRIV_NAME}" \ | |
//homedir:"$(cygpath -w ${EMPTY_DIR})" //active:no; then | |
echo "ERROR: Unable to create Windows user ${PRIV_USER}" | |
exit 1 | |
fi | |
# | |
# Add or update /etc/passwd entries | |
# | |
touch /etc/passwd | |
for u in "${PRIV_USER}" "${UNPRIV_USER}"; do | |
sed -i -e '/^'"${u}"':/d' /etc/passwd | |
SED='/^'"${u}"':/s?^\(\([^:]*:\)\{5\}\).*?\1'"${EMPTY_DIR}"':/bin/false?p' | |
mkpasswd -l -u "${u}" | sed -e 's/^[^:]*+//' | sed -ne "${SED}" \ | |
>> /etc/passwd | |
done | |
mkgroup.exe -l > /etc/group | |
# | |
# Finally, register service with cygrunsrv and start it | |
# | |
cygrunsrv -R msys2_sshd || true | |
cygrunsrv -I msys2_sshd -d "MSYS2 sshd" -p \ | |
/usr/bin/sshd.exe -a "-D -e" -y tcpip -u "${PRIV_USER}" -w "${tmp_pass}" | |
# The SSH service should start automatically when Windows is rebooted. You can | |
# manually restart the service by running `net stop msys2_sshd` + `net start msys2_sshd` | |
if ! net start msys2_sshd; then | |
echo "ERROR: Unable to start msys2_sshd service" | |
exit 1 | |
fi |
Another way to get the right MSYSTEM
environment, put the following at the top of your ~/.profile
:
if [ -n "$SSH_CONNECTION" ]; then
export MSYSTEM=MINGW32
source /etc/profile
fi
Windows 10 is installed msys2. This script does not work with me. I set the tmp_pass to be 123 for the all accounts and I tried to login by ssh it refused. (I checked sshd_config, PasswordAuthentication is yes). I tried to login the new privileged account created by the script from Windows with password 123 with success.
I tried to login with username sshd_server and password ssh_server and encounter same problem with @sushovan-dw.
Can someone help
Edited, after I had to reinstall windows recently (2018-05-08, original message is from December 2017), I was confused reading my own instructions so I improved them.
1 A user must be created in /etc/passwd (msys2 doesn't create a user by default, and I don't mean the sshd ones created by this script), I found in https://sourceforge.net/p/msys2/discussion/general/thread/76612760/ that doing /usr/bin/mkpasswd prints the windows users as passwd lines. Use your user line from that "output" and paste it in /etc/passwd
2 Then run passwd in the MSYS2 console to give the user a password, this will change your current user password in windows too
3 Create a rule for the /usr/bin/sshd.exe in the windows firewall, for the port configured in /etc/ssh/sshd_config (default is 22)
4 Run a MSYS2 console as admin and run this script, it should tell you that a sshd service has started
5 Reboot?
6 Profit
A user must created in /etc/passwd
if [ ! /etc/passwd ]; then
mkpasswd -c > /etc/passwd
touch /var/log/lastlog
echo AcceptEnv MSYSTEM >> ~/etc/ssh/sshd_config
echo To start shell as ${MSYSTEM} use:
echo MSYSTEM=${MSYSTEM} ssh ...
fi
Hello! This works good! But be careful:
I accidentally messed upp... Somehow the script did not work, so I started changing stuff, I changed the PRIV_USER to my own computer user, and then the password was changed to a random password, so now I can not access my computer anymore...
Besides from this, I have run it on another computer where it worked very well!
Thanks :)
If you're a casual Windows 10 user who has admin rights and who hasn't bothered to set a Windows password, then the following method works (bear in mind that there are a couple of unnecessary steps here, but at least this really does work):
1. Run MSYS2 shell as admin.
2. pacman -S --noconfirm openssh cygrunsrv mingw-w64-x86_64-editrights
3. passwd <username> # Enter a password here.
4. Reboot your computer. Log in this time with the password you just set. Run MSYS2 shell as admin again.
5. ssh-keygen -A
6. ssh-keygen -b 4096
7. :>| /var/log/lastlog
8. mkpasswd -c >/etc/passwd
9. Run the script. Some of the messages look like errors. They aren't; it's just the way the script's been written.
Remember to open port 22 in your Windows firewall.
1. To stop the service, use: net stop sshd
2. To remove the service, use: cygrunsrv -R sshd
3. To stop having to enter a Windows password, run MSYS2 as admin again and use: passwd <username>, pressing return twice to leave the password blank.
Thanks for this script! I have Windows 10 Home, which doesn't have the "run as Admin" option on Start items. But I can run Power Shell as admin, via the Windows-x menu, and run mingw64.exe from there. Then the script runs. After disabling firewall on private network, I can login.
I just used this script successfully on Windows10. But I'm already running Cygwin sshd on the same machine, so I had to make some adjustments:
- Edited this script to replace "sshd" with "msshd"
- Edited /etc/ssh/sshd_config to specify a different port (instead of 22)
- Added a rule to Windows Firewall to allow incoming TCP on that port
- Picked a new fake hostname
- edited my .bashrc file to override $HOSTNAME, hostname and uname
These two steps had to be done for MSYS2, Cygwin and for every machine I connect from:
- Edited /etc/hosts to give the fake hostname the same IP address as the real Windows machine
- Edited ~/.ssh/config to specify the right port for the new fake hostname
Everything works fine!
The only potential issue I see is that user "sshd" is apparently used by both Cygwin and MSYS2, though it hasn't caused any problem yet.
Anyone have a solution to "passwd: unrecoverable error 8646" in Win10 Pro 1809 64-bit?
MSYS ~
# passwd rcpao
New password:
Re-enter new password:
passwd: unrecoverable error 8646
Try again.
New password:
Re-enter new password:
passwd: unrecoverable error 8646
Try again.
New password:
Re-enter new password:
passwd: unrecoverable error 8646
MSYS ~
#
@InBetweenNames @ghost @AllenKll :
In addition to
# mkpasswd.exe -l > /etc/passwd
I had to do
# mkgroup.exe -l > /etc/group
Then I restarted the sshd service.
# net stop sshd
# net start sshd
after that, I was able to login and no longer saw the chown
error in sshd.log
@samhocevar, can you put a license on this script? WTFPL2 is ok. ;-)
Q: How I can view windows root (disk C,D, others)? In cygwin default access here: /cygdrive/c$ Where its in msys2???
A: cd /c/ to access C: cd /d/ for D:
But why there are no ready symlinks for a quick go? Like in CygWin?
@samhocevar I ran into the seteuid
issue but could not fix it with the passwd -R
method. I found this thread and finally solved the issue by
- running
sshd
as theSYSTEM
user - removing
/etc/passwd
and/etc/group
Now I can log in again with local and LDAP accounts. Both the additional privileged user and the files seem to have been workarounds which are no longer necessary and even problematic nowadays. I'm not sure wether the unprivileged sshd
user is still necessary, but you could completely remove the PRIV_USER
, /etc/passwd
and /etc/group
parts from the script.
@bk90 thanks for the feedback; this script is indeed in need of some cleanup, I will test your suggestions.
@samhocevar, I made the changes mentioned by @bk90 and published an updated version of the script here: https://www.msys2.org/wiki/Setting-up-SSHd/
@elieux the script in msys-wiki is missing the generation of tmp_pass
. What's more, it still contains the unnecessary PRIV_USER
.
Thanks, @kolewu. I don't know how I missed this. Should be fixed in a few minutes.
Shouldn't this be renamed from gistfile1.sh
to msys2-sshd-setup.sh
?
@elieux Thanks for the quick correction. There is an important information that should be added somewhere (but I don't know where): This configuration of sshd only works for local user. It's not possible to login as domain user (this produces the seteuid
fatal error) and I haven't found the missing bits and pieces (passwd -R
isn't enough).
For me the more practical solution was in this link
the section Setting up SSH , without user with privileg...for my desktop....
the script do not run for me ...many issues, thanks
https://www.booleanworld.com/get-unix-linux-environment-windows-msys2/
thanks! this worked for me.
There is an important information that should be added somewhere (but I don't know where): This configuration of sshd only works for local user. It's not possible to login as domain user (this produces the seteuid fatal error) and I haven't found the missing bits and pieces (passwd -R isn't enough).
@kolewu Thanks for a very helpful note. Apparently this is solved in https://github.com/rkitover/windows-alt-sshd-msys2
I've tried several different versions of this script including this one, https://www.msys2.org/wiki/Setting-up-SSHd/, and https://github.com/rkitover/windows-alt-sshd-msys2/blob/master/msys2-alt-sshd-setup.sh. All have issues.
When I run this script I get the below error:
"The user name could not be found.
More help is available by typing NET HELPMSG 2221.
The option //ADD is unknown.
The syntax of this command is:
NET USER
[username [password | *] [options]] [/DOMAIN]
username {password | *} /ADD [options] [/DOMAIN]
username [/DELETE] [/DOMAIN]
username [/TIMES:{times | ALL}]
username [/ACTIVE: {YES | NO}]
More help is available by typing NET HELPMSG 3506.
ERROR: Unable to create Windows user "
How do I get around this? I tried jouven's instructions. I ran /usr/bin/mkpasswd | grep using my personal account and copied that line into /etc/passwd. I already have a password on my account, but still tried passwd and it said "You may not change the password for ?. I thought that was fine so I continued on and ran the script and got the error above. Any ideas? Thanks
@wapiti96 The script uses //ADD
to tell the msys2 path handling converter to not treat it as a path and convert it to /ADD
.
Make sure you are not setting the environment variable MSYS2_ARG_CONV_EXCL
or other variables related to path conversion.
if you want to execute a windows app say notepad you are running windows service you have to use a weird hack like this
MSYS2_ARG_CONV_EXCL="*" schtasks /create /sc once /tn "NotepadIn10Sec" /tr "notepad.exe" /st $(date -d @"$((current_time=$(date +%s) +40 ))" +"%H:%M:%S") && ( sleep 50; MSYS2_ARG_CONV_EXCL="*" schtasks /delete /tn "NotepadIn10Sec" /f)
assuming you're logged in as the same user
and in case you're on a firewall:
cygrunsrv -R msys2_autossh ; cygrunsrv -I msys2_autossh -d "MSYS2 autossh" -p "/usr/bin/bash.exe" -a "autossh -M 0 -i /home/myuser/.ssh/id_rsa -o UserKnownHostsFile=/home/myuser/.ssh/known_hosts -R 9090:localhost:22 remoteuser@192.168.59.30 -N" -y msys2_sshd
Anyone have a solution to "passwd: unrecoverable error 8646" in Win10 Pro 1809 64-bit?
MSYS ~ # passwd rcpao New password: Re-enter new password: passwd: unrecoverable error 8646 Try again. New password: Re-enter new password: passwd: unrecoverable error 8646 Try again. New password: Re-enter new password: passwd: unrecoverable error 8646 MSYS ~ #
metoo
@improve100 just use a key instead
Got it to work for my computer and user that is connected to a domain at work. Here are the things I had problems with:
passwd -e "${PRIV_USER}"
didn't work, removed the line and used the local user and group manager to set the password to never expire.mklink /D C:\msys64\home\username \\server\home\userhomedir