The hosts, set a tough victory target of 386, moved from their overnight score of 67-3 to 134-5 in their second innings by lunch on the final day at the Sinhalese Sports Club.
Skipper Angelo Mathews kept Sri Lanka’s hopes alive of forcing a draw with an unbeaten 56. Kusal Perera was the other batsman at the crease on 12, with Sri Lanka needing 252 more runs to win.
Sri Lanka added seven runs to their overnight score when they lost opener Kaushal Silva for 27, caught at mid-wicket by Cheteshwar Pujara attempting to hook Umesh Yadav.
Left-hander Lahiru Thirimanne made 12 when an alert Lokesh Rahul at silly point pounced on the ball and held it on second attempt as a delivery from Ravichandran Ashwin found an outside edge.
Mathews settled in to strike seven boundaries and remained the main hurdle in India’s bid to win their first Test series in Sri Lanka since 1993.
Sri Lanka won the opening Test in Galle by 63 runs, but India drew level with a 278-run win in the second match at the P. Sara Oval in Colombo.