The 28-year-old ripped through the top order to restrict the visitors to 230 for eight after they had won the toss and elected to bat.
Dravid, who became the sixth batsman in history to reach 10,000 ODI runs scored a match-winning 66 as India overcame early hiccups to surpass Sri Lanka's 230-8 in the 47th over.
Zaheer dismissed openers Sanath Jayasuriya (two), Upul Tharanga (one) and the in-form Kumar Sangakkara for a duck, before claiming the wickets of Farveez Maharoof (14) and Malinga Bandara (two) to finish with five for 42.
Tourists fought back through the middle and lower order to post a challenging total.
Russel Arnold (66 not out) and Tillakaratne Dilshan (42) put on 89 for the sixth wicket after half the side was back in the pavilion for 91 by the 24th over.
India, in reply, slipped to 35-2 by the fifth over as Virender Sehwag was caught off Dilhara Fernando for 12 and Sachin Tendulkar was bowled by Nuwan Kulasekara for one.
Sourav Ganguly made 48 to boost the score before Dravid and Mahendra Dhoni (67 not out) sealed India's win with a fifth-wicket stand of 133.
Dravid was unlucky to be run out four runs short of victory when bowler Malinga Bandara deflected a hit from Dhoni on to the wicket with the non-striker out of his crease.
Dravid joined team-mates Tendulkar and Ganguly, Inzamam-ul-Haq of Pakistan, Sanath Jayasuriya of Sri Lanka and Brian Lara of the West Indies in the exclusive 10,000-run club when he reached 22.
The Indian captain, a veteran of 309 one-dayers, now has 10,044 runs with 12 hundreds and 77 half-centuries.
Earlier, Zaheer grabbed the first three wickets in eight balls as he surpassed his previous best of 4-19 against Bangladesh in Dhaka in 2003.
Ganguly led India's inspired display in the field with a brilliant catch to dismiss veteran Jayasuriya.
Ganguly, 34, ran swiftly from mid-wicket to square leg and then dived full length to hold a skier one-handed after Jayasuriya fended at a rising ball from Zaheer.
Zaheer trapped Upul Tharanga leg-before three balls later and clean-bowled Kumar Sangakkara, a century-maker in the previous game, for duck in his next over.
Skipper Mahela Jayawardene and his predecessor Marvan Atapattu put on 76 for the fourth wicket before both fell in successive overs to make Sri Lanka 91-5.
Atapattu was held low at square-leg by Tendulkar after making 42 and Jayawardene fell leg-before to Harbhajan Singh for 30.
Dilshan and Arnold rebuilt again in the middle overs before Harbhajan had Dilshan caught at the wicket in the 42nd over to take his second wicket.
The final match will be played in Visakhapatnam on Saturday. The opening contest in Kolkata was abandoned due to rain while the visitors won the second match at Rajkot by five runs.
The series is the last for both teams before they head to the Caribbean for the World Cup starting on March 13.