It was a straight sets victory, 6-4 7-6, but the Swiss was made to work hard for it as the Russian pushed his legendary opponent throughout.
Federer grabbed the crucial break in the opening set to take command of the match and did not allow Khachanov back in.
'You don't have to fool yourself' - Nadal accepts Djokovic will win most Grand Slams
The Russian forced a tie-break in the second set but the Australian Open champion was again too strong and took it 7-5 to seal victory.
Federer will now play Alexander Zverev in what will be his 11th final in Halle alone.
The German defeated France's Richard Gasquet in the second semi-final, 4-6 6-4 6-3.
Gasquet, a two-time Wimbledon semi-finalist, grabbed the first set against Zverev with a break at 5-4.
But he quickly fell behind in the second as Zverev, a finalist last year, who has already won three titles in 2017, charged to a 4-2 lead and held on to take the set.
The world number 12 booked his final spot after breaking at 3-3 and finishing the Frenchman off with another break to set up the showdown with Federer.
Despite a shock exit from Stuttgart on his comeback last week, Federer has improved in Halle and has not lost a set.
"I thought it was extremely close, especially that second set," Federer, who has never won a tournament nine times, told reporters.
"I'm still just very happy how I was able to close it out in the (tie-)breaker," said the 35-year-old.
Federer, the 18-times Grand Slam champion, who captured the Australian Open, Indian Wells and Miami titles this year, has yet to drop a set at the tournament.
Image credit: Getty Images
'Federer faces reality check' - Wilander
'They're not intimidated anymore' - Djokovic 'vulnerable' to rising stars says Wilander