How do port-scanners ... get so much detailed information about the service and the OS
Depends on the specific service. For SSH a simple TCP connection to the service is sufficient since the server will reply with this information, i.e.
$ telnet some-openssh-server.example.com 22
SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
Similar trivial are information to gain from HTTP since systems commonly announce these information. Of course servers might actually lie about their version and OS, in which case this lie will usually be accepted by the scanner.
How can I make it so that no information is revealed?
The best way is to prevent the scanning in the first way. This can be done by only accepting connections from specific IP addresses, by requiring some port knocking before the port gets opened or similar. One might also try to change the provided details in the server configuration. If this is possible and how it is done depends on the specific server software.