Sri Lanka were 240 for five at the close of play, with their last two recognised batsmen at the crease, after being set to make an improbable 488 to win.
Rabada twice dismissed set batsmen, on both occasions with the second ball of a new spell.
He trapped Kaushal Silva leg before wicket for 48 with his second ball after tea.
Then, late on a hot afternoon, he broke a 75-run partnership between captain Angelo Mathews and Kusal Mendis.
A fast, short delivery bowled from around the wicket induced an involuntary ramp shot by Mendis, who was caught behind by wicketkeeper Quinton de Kock for 58.
In contrast to the first innings, when they were bowled out for 205, with several batsmen playing poor strokes in seam-friendly conditions, South Africa had to work hard for their wickets on a pitch which had lost most of its earlier life.
It took a moment of hesitation to break an opening stand of 87 between Dimuth Karunaratne and Silva, who defied the South African bowlers for 145 minutes before Karunaratne was run out for 43 in the 33rd over.
Silva pushed a ball from left-arm spinner Keshav Maharaj into the covers and set off for a run.
Both batsmen hesitated momentarily in mid-pitch, JP Duminy picked up and released the ball quickly to wicketkeeper De Kock, who broke the stumps with a diving Karunaratne just short of the crease.
Two overs later Kusal Perera attempted an extravagant cut shot and was caught behind, also off Maharaj.
Silva and Mendis saw Sri Lanka through to tea before Rabada’s first breakthrough was followed by a fine partnership between Mathews and Mendis, with the 21-year-old Mendis playing some impressive strokes, hitting nine fours in a 90-ball innings before falling to Rabada.
Maharaj, who bowled 22 overs unchanged, had Dinesh Chandimal caught at mid-on, with the batsman charging down the wicket. He had been dropped by Stephen Cook at mid-off trying a similar shot five runs earlier.
Mathews and Dhananjaya de Silva saw out the day, with De Silva surviving on review after being given out leg before to Kyle Abbott, bowling with the second new ball, two overs from the close.
Earlier South African captain Faf du Plessis declared with his team on 406 for six in their second innings.
He and De Kock added 55 runs in 10.5 overs on Thursday before De Kock missed a sweep against left-arm spinner Rangana Herath and was leg before wicket.
De Kock made 69 off 86 balls and Du Plessis was unbeaten on 67, also made off 86 deliveries.
The pair put on 129, a record sixth wicket partnership for South Africa against Sri Lanka. It was also the third century stand of an innings during which South Africa scored at an average of 4.47 runs an over.